Django的未承载远程存储服务器应用程序

django-remotestorage的Python项目详细描述


Django远程存储

UnhostedremoteStorage服务器实现

此应用程序是较早版本的服务器(存储)实现 远程存储API版本,在此处指定:

http://www.w3.org/community/unhosted/wiki/RemoteStorage-2011.10

它的某些部分(特别是webfinger、oauth2,因为我使用了更新的 当时可用的规范)可能与 当前API:

https://tools.ietf.org/id/draft-dejong-remotestorage-00.txt

但由于实验性api的remotestorage.js 0.7.0仍在 在那个时候,我还没有测试它是否适用于 目前的执行情况。

包(和django应用程序)在过去被称为django unhosted 最终更名。如果您使用的是django未粘贴包,请阅读 那notes on migration 在下面 Installation 区域

远程存储

想法是您可以拥有存储帐户(使用任何策略和 在host1和一些webapp上(比如,一些可视化编辑器 word)在host2上。

要在webapp中编辑文档,通常host2必须实现 某种用户注册、存储(比如docs.google.com)的方式 编辑的文档等。

使用远程存储,此存储不必在host2上,因此您不必 必须在那里实现一些复杂的策略和经过身份验证的存储 要启动功能齐全的webapp,它可以打开文档并将其保存到任何 支持协议的远程主机(基本上是从 WebDAV,上面是OAuth2)。

host1可以是您的vps,客户机本身(特别容易 直接IPv6,或通过某些服务提供的IPv4,如 pagekite),一些可靠的云提供商或 无论什么。

为了完全理解它是如何工作的,我建议看看OAuth2, webdav、cors和webfinger,它们基本上都是 用于实现协议。

这个django应用程序为host1完全实现面向web的存储,完成 使用用户注册表单(可选,用户可以通过其他 django应用程序或通过django管理界面,否则),客户端访问 管理界面和一个简单的演示客户端。

安全性

因为applicaton是一个面向Internet的公共接口,可以 重要)我不是安全专家或专家,我 建议在存储任何敏感的 里面的数据。

数据丢失或损坏更容易预防(而且备份时间很长 在这里,顺便说一句)比安全漏洞,所以,再一次,请看 给自己编代码,找出我有盲点的问题 提到缺乏技能)为,这样就找不到自己了。

例如,在另一个 存储服务器实现can be found here, 在那儿学乐视。

安装

要求

目前oauth2app是not on PyPI,但是 pip可以直接从github安装它。

应用程序的各种接口使用一些外部资源,如Twitter Bootstrapcss文件(从 bootstrapcdn.com)和 remoteStorage.js, 如果您使用https 接口-来自本地URL,如果在静态根目录中可用。见 “定制/接口”了解详细信息。

从Django的迁移未显示

这个包裹过去被称为django unhosted,但后来决定 在太迟之前把它改名。

不幸的是,没有简单的方法可以重命名django应用程序和python 包,特别是如果不希望保留旧的包名称 所以必须采取一些手动步骤 迁移到新的(django remotestorage)应用程序/包。

  • 卸载django unhosted python包(通过 pip uninstall     django-unhosted、操作系统工具或删除模块 手动路径)。
  • 全部重命名名称为“django_unhosted”的数据库表 从“django_remotestorage”开始。很多简单易用的 图形用户界面工具(如pgadminphpPgAdminphpMyAdminphpSQLiteAdmin等)或 本机cli接口(sqlite3 /path/to/db.sqlitepsqlmysql等)可用于此。
  • 更新settings.py和urlconf以从 “django_remotestorage”模块,而不是“django_unhosted”。替换 变量名中的所有“unhosted”如果用于 设置.py。
  • 如果有自定义的urlconf和/或模板,请替换对 具有“remotestorage”的“unhosted”命名空间。

它应该相当简单,但是可以随意打开问题或 contact developers 如果所描述的过程不适合你。

部署/配置

django应用程序作为“django项目”的一部分部署,该项目位于 它是最小的-只有几个configuration files, 指定要使用的数据库,以及应处理哪些应用程序 网址。

tl;dr

从头开始的简单安装/设置可能如下所示。

安装应用程序本身(或者不安装,只需将其签出到 项目总监:

pip install django-remotestorage

…或者,直接从git主分支安装:

pip install 'git+https://github.com/RemoteStorage/django-remotestorage.git#egg=django-remotestorage'

…也可以手动操作:

git clone https://github.com/RemoteStorage/django-remotestorage.git
cd django-remotestorage
python setup.py install
pip install -r requirements.txt # or download/install each by hand as well

上面提到的“pip”工具通常应该随附操作系统, 否则请参见pip installation docs。不要 使用“easy_install”除了安装pip本身。

以类似的方式安装oauth2app:

pip install 'git+https://github.com/hiidef/oauth2app.git#egg=oauth2app'

然后创建并配置django项目:

cd
django-admin.py startproject myproject
cd myproject

# Update settings.py (sqlite3 is used as db here) and urls.py
sed -i \
    -e 's/'\''ENGINE'\''.*/"ENGINE": "django.db.backends.sqlite3",/' \
    -e 's/'\''NAME'\''.*/"NAME": "db.sqlite",/' \
    -e 's/STATIC_ROOT *=/STATIC_ROOT="./static"/' \
    myproject/settings.py
echo -e >>myproject/settings.py \
    'from django_remotestorage.settings_base import update_settings' \
    '\nupdate_settings(__name__)'
sed -i \
    -e '1afrom django_remotestorage.urls import remotestorage_patterns' \
    -e 's/# Examples:.*/("", include(remotestorage_patterns)),\n\n\0/' \
    myproject/urls.py

# Create database schema and link app static files to STATIC_ROOT
./manage.py syncdb --noinput
./manage.py migrate django_remotestorage
./manage.py collectstatic --noinput --link

# Run simple dev server
./manage.py runserver

(由于WebFinger协议需要某种XRD身份验证, 像https一样,在这样一个简单的设置上无法正常工作

下面将更详细地解释配置过程。

django项目配置

主要思想是两个配置文件(在django项目中)需要 更新了-settings.py和url.py。

有几种方法可以更新django settings.py以使用应用程序:

  • 如果它是django项目中唯一的应用程序,而且没有自定义 settings.py已经,选项来自 django_remotestorage.settings_base 模块可以直接导入。

    为此,在的end中添加以下行 “{your_app_name}/settings.py”(或 DJANGO_SETTINGS_MODULE 使用)文件:

    from django_remotestorage.settings_base import *
    

    它将导入所有选项(必须是 更改)在原始文件中定义的以上。

    注意,overidden选项列表包括已安装的应用程序, 中间件类等等,它们不仅经常被定制, 但通常是特定于安装的django版本的,因此您可以 或者将导入行插入到 因此在它之后定义的所有内容都将覆盖 导入的选项。

  • 如果已经有一些自定义设置.py文件可用,则 django_remotestorage.settings_base.update_settings助手函数 可用于更新配置而不盲目重写任何 选项

    它可以在settings.py文件的末尾使用,如下所示:

    from django_remotestorage.settings_base import update_settings
    update_settings(__name__)
    

    更改的完整列表可以在 开始 django_remotestorage.settings_base 模块。

    “update_settings”功能也有一个可选的“only”和 “ignore”关键字(应为选项名的iterable),它可以 用于控制应更新或显式更新哪些参数 保持原样。

    <>这应该是更加安全、灵活和未来证明的合并方式。 必要的选项更新与现有的(站点特定)配置。

  • 手动更新文件。

    大多数设置的默认值可以在django documentation中找到。

    对于类列表类型选项,可以省略重复值。 注意,中间件类的顺序很重要。

    OAUTH2_CLIENT_KEY_LENGTH = 1024
    OAUTH2_SCOPE_LENGTH = 2048
    
    TEMPLATE_CONTEXT_PROCESSORS = (
        ...whatever is already there...
        'django.core.context_processors.csrf',
        'django.core.context_processors.request',
        'django.contrib.messages.context_processors.messages',
        'django_remotestorage.utils.external_resources_context',
    )
    
    TEMPLATE_LOADERS = (
        ...whatever is already there...
        'django_remotestorage.apps.webfinger.xrd_gen.Loader',
    )
    
    MIDDLEWARE_CLASSES = (
        ...whatever is already there...
        <remove 'django.middleware.csrf.CsrfViewMiddleware', if it's there>
        ...whatever is already there, except for ConditionalGet / FetchFromCache...
        'django.contrib.messages.middleware.MessageMiddleware',
        ...ConditionalGetMiddleware and FetchFromCacheMiddleware (and such), if used...
    )
    
    INSTALLED_APPS = (
        ...whatever is already there...
        'django.contrib.messages',
        'django_remotestorage',
        'oauth2app',
        'south',
    )
    

    如果没有使用,安装的应用程序中应该省略“south”。

无论如何,如果你只是创建的Django项目(使用 “django-admin.py startproject”或其他),请确保查看 它是settings.py文件,至少可以编辑数据库、媒体和 静态选项。您可能还想设置其他(光学)设置 那里-时区、管理员、日志记录等。

对于url.py,只需将以下行添加到url模式(导入 来自django_remotestorage.url模块的remotestorage_模式 事先):

('', include(remotestorage_patterns)),

所以看起来是这样的:

...
from django_remotestorage.urls import remotestorage_patterns
...
urlpatterns = patterns('',
    ('', include(remotestorage_patterns)),
...

将所有应用程序URL添加到根路径(用于完整列表 在这些路径中,请参见the module code)。 要有选择地禁用某些组件,请参阅“自定义” 区域

数据库架构

通常的做法是为 应用程序(如果出现“无法导入设置”错误,请确保运行 与“settings.py”文件路径相同的文件:

django-admin.py syncdb

如果South app已安装(并指定 在已安装的应用程序中,还应使用它的迁移创建 提供的桌子:

django-admin.py migrate django_remotestorage

该命令也可以(而且应该)在django remotestorage app之后运行 更新以对数据库架构应用任何可能的更改。

运行

几乎所有支持 WSGI 协议可以与django一起使用-这里没有特定的应用程序, 只是普通的django,它(通常)用作一些httpd的后端 通过wsgi。

参见deployment process上的django文档 一般说明。

定制

成分

应用程序由几个独立的组件(子应用程序,绑定到 URL路径通过 django_remotestorage.urls):

  • webfinger(名称:webfinger,url: {包含前缀}/.已知/主机元,{包含前缀}/webfinger; 看见 django_remotestorage.apps.webfinger.urls, 其他子应用程序也有类似的urlconf文件)。
  • oauth2(名称:oauth2,url:{include_prefix}/oauth2)。
  • 存储api(名称:api,url:{include_prefix}/api)。
  • 帐户/客户端管理(名称:“account”,url: {包含前缀}/帐户)。也可以使用 以下名称:“account_auth”(登录/注销表单/链接), “账户认证管理”(注册表) “客户机管理”(客户机/应用程序访问管理界面 对于已登录的用户)。“account”是所有这些的别名 接口。
  • 演示客户端(名称:demo,url:{include_prefix}/)

一些组件相互提供链接(例如,webfinger 在提供的xrd/json数据中提供到oauth2和api的链接,解析为 “远程存储:{app}:{view_name}”,因此您可以将这些应用重新绑定到任何 url,只要为django “reverse()” function提供相同的名称空间/视图名称 和“url”模板标记。

当包含“django_remotestorage.url.remotestorage_patterns”时 直接(不是来自单个组件的urlconf), “remotestorage_components”settings.py选项可以设置为iterable 应启用的组件,例如:

REMOTESTORAGE_COMPONENTS = 'webfinger', 'oauth2', 'api'

…将只启用存储api、oauth2和webfinger子应用程序-bare 功能性远程存储节点的最小值。除非有其他办法 验证django用户(如 django.contrib.auth.views.login 或者django.contrib.admin)已启用,也可能需要 启用“account_auth”接口以通过OAuth2授权。

如果urlconf中省略了“account”(或其部分)和“demo”应用程序 完全(如果不需要的话),在OAuth2中不会有任何指向它们的链接 访问确认界面。它们的界面页面和功能 无法访问。

“api”和“oauth2”子应用程序未链接到任何其他组件 也可以单独使用 嗯(例如,如果授权服务器和存储在不同的 但它们必须共享一个数据库,以便api能够 验证验证令牌。

OAuth2

强烈建议增加数据库字段长度(使用 oauth2app settings之前 首次运行syncdb:

  • OAuth2_客户端密钥长度=1024(默认值:30)
  • OAuth2_scope_length=2048(默认值:255)

有关 为什么要这么做。

另一个重要的可调参数是oauth2_access_token_expiration(默认值: 3600=1小时),至少在remotestorage.js 0.6.9(“稳定”下) 在写的时刻)-本质上设置了最大间隔。 需要访问OAuth2接口并获取新的访问令牌,因为 remotestorage.js似乎无法刷新这些。

网指

如果 webfingerhost-meta 对域的请求应该包含比 远程存储,它们可以通过替换webfinger应用程序进行扩展 完全或添加自定义模板。

webfinger应用程序正在使用“webfinger/host{meta.{xml,json}”和 “webfinger/webfinger.{xml,json}”模板,由提供 django_remotestorage.apps.webfinger.xrd_gen.loader或生成 动态(对于json,如果找不到模板provide)。

请参阅中的示例XML模板 django_remotestorage/templates/webfinger/{host_meta,webfinger}.xml.example

存储/webdav

如果远程存储由(可配置的)Django Storage API支持。

默认情况下, DEFAULT_FILE_STORAGE 使用存储类。不同的存储类可以由 “remotestorage\u dav\u storage”参数(传递给 get_storage_class)。

存储api实现的示例可能包括:

但基本上有一个客户机可以存储几乎所有的数据 技术-只需谷歌它,安装和设置远程存储 (或默认的文件存储)。

默认存储(文件存储)参数可以配置为 媒体URL和媒体根目录 settings,请参阅 “Managing files”姜戈 文档部分了解详细信息。

还有一些优化参数:

  • 远程存储发送文件(bool,默认值:false)

    将storage.path(如果后端支持)通过 “x-sendfile”头而不是请求时的实际内容,因此 该响应可以由前端守护程序直接提供,而无需 涉及后端应用程序。

  • remotestorage_dav_accel(字符串,默认值:无)

    将“x-accel-redirect”标题设置为的空HttpResponse返回 指定的前缀(可以是空字符串)加上请求的路径,因此 实际的响应可以由apache mod_accel提供。

  • 远程存储重定向(bool,默认值:false)

    返回重定向到媒体URL(由storage.url方法生成)。用过的 仅当媒体URL设置为非空字符串时。

    只有在检查oauth2app生成的承载之后才能提供这些url http“authorization”头中的令牌,可以使用django(或自定义 或者一些智能httpd。

    不要将httpd配置为在没有 授权,因为每个人都可以绕过OAuth2 通过猜测文件路径就可以访问远程存储中的任何内容 或者从js获取/重用它们,这非常容易利用。

接口

通常的演练-将自己的模板放到加载程序中,在 设置.py。

这些页面上提供的外部资源可以放在 静态根目录将由本地httpd提供服务。见 django_remotestorage.utils.external_resources_context 上下文处理器以获取详细信息。

如果为这些接口提供服务,请特别注意使资源成为本地资源 通过https-如果mitm可以放置任何 javascript(通过普通http加载)到页面。

注意,如果不需要的话,可以禁用任何/所有ui, 只需使用remotestorage_components选项(如“组件”中所述) 或者不包括在urlconf中,樱桃采摘 实际上是需要的。

定制的一个常见情况是需要将整个应用程序放入 子路径(“/remotestorage”在示例中)可以通过放置 这将进入项目的根url.py:

from django.conf.urls import patterns, include, url

from django_remotestorage.apps.webfinger.urls import host_meta_patterns
from django_remotestorage.urls import remotestorage_patterns

urlpatterns = patterns('',
    url(r'', include(host_meta_patterns)),
    url(r'^remotestorage/', include(remotestorage_patterns)),
)

这样,演示客户端将在“/remotestorage”url和所有 链接将包括该前缀(例如来自 webfinger将指向“/remotestorage/oauth2/authorize”)。

不过,请确保webfinger应用程序的主机元视图是available at a well-known url “/.well-known/host-meta”,因此是“主机元模式”的特例 从根链接。

命令

访问令牌清除[选项][用户名…]

删除过期的OAuth访问令牌(仅用于用户名,如果指定) 从数据库中。

可以偶尔从cron运行(使用–verbosity=0来抑制活动 报告)以防止令牌数无限增长,删除 未刷新或即将过期(负宽限期)的。

用法示例:

% ./manage.py access_token_cleanup -v2 -n -t 3600 test
Removing token: id=1, user=test, client_name=localhost, expired=2012-07-31 03:24:30+06:00.
1 access token(s) removed.

已知问题

这些是与实现相关的问题,而不是 协议本身(并不意味着没有后者, 只是那不是他们的地方。

网指

  • 不容易支持signed XRD 目前。签名的staticxml“模板”(或仅提供文件) 如果TLS不是一个选项,则可以使用httpd)作为解决方法。

OAuth2

  • 存储对象路径(想想“public/myphoto.jpg”)用作OAuth2 远程存储的“作用域”。oauth2app基本上只保留一个表 这些(将它们视为一组有限的预先能力)。

    这里的问题:

    • OAuth2App将“scope”存储为255个字符的键,而路径/ 集合名称可能更长。上游pull request指定 字段长度已合并(截至2012年7月19日),因此请使用任何更新的 中具有足够大的oauth2_scope_length参数的版本 settings.py(它doesn’t really affect performance 现代数据库,只是让你的生活更艰难)。
    • 目前,OAuth2App检查访问范围(范围)的存在性。 尽管可以访问 其中一些可能未经用户授权,需要临时 造成这种混乱。上游拉取请求: https://github.com/hiidef/oauth2app/pull/32
    • 在维护 (在本例中没有意义)表。
  • remotestorage.js 0.6.9(“目前稳定”的版本)有一个known issue 将遗留的“path1,path2”作为“scope”传递,进一步复杂化 为OAuth2App准备的东西 能力,根据规范)。

    解决方法是通过缺少“:rw”后缀来检测旧格式 并通过发出重定向来更新地址中的“scope”。

    注意,由于路径可能包含逗号,“path1,path2”可以是 模棱两可(因为这个问题),可以被视为 “路径1:rw”和“路径2:rw”或“路径1,路径2:rw”。当前实施 如果没有结肠脱落,则选择前一种解释 后缀。

  • remotestorage.js 0.6.9(“目前稳定”的版本)使用主机名 应用程序站点的OAuth2客户机ID,在OAuth2App中对应 到“key”字段,默认情况下只有32个字符长, 对某些主机名来说可能不够,但可以(而且should!)是 由django中的oauth2_client_key_length参数配置 项目设置.py。记住在syncdb或update之前 稍后是表列。

    可能的解决方法是使用哈希作为客户端的ID 内部和重定向远程存储请求 “client_id=hostname.com”改为 “客户ID=sha1:bbc21f0ccb5dfbf81f5043d78aa”。

    我不明白为什么客户ID在 现在,如果有原因的话,请报告一个问题,somE类 自动迁移到散列可能随时都可以部署。

  • 目前OAuth2App是not on PyPI, 但是pip可以直接从github安装它。

WebDAV

  • CSRF中间件 (django.middleware.csrf.CsrfViewMiddleware) 必须禁用,因为remotestorage.js不通过django csrf 令牌以及put(和类似的)请求。是有选择性的 不过,通过应用程序窗体的decorator启用。

  • 数据当前存储在django存储中,而路径元数据 是通过django数据库api存储的,它引入了 故障点(以及两者之间同步丢失的可能性); 因为一个数据没有另一个是无用的。

    似乎没有任何简单的方法可以解决这个问题-将路径数据存储在 存储密钥不适用于任何驱动程序,将其推到内容中 当这些内容将由python以外的任何东西提供服务时将不起作用 (比如,httpd)和在数据库中存储文件只在相对 小文件。

    所以一定要备份数据库和实际的存储,或者写 一些特定于存储的kludge也可以在那里存储元数据。例子 会在post-save django signal中添加一个钩子, 它将从storageobject.data.name和store获取存储路径 一些“{name}.meta”文件以及序列化的模型数据。

待办事项

  • 客户端(应用程序,请求访问)欺骗-返回假的 “授权作用域”,但将它们存储在某个地方以拒绝 实际访问或提供随机垃圾。

    这个想法是为了防止这种情况,在twitter和android上很常见 平台,当应用程序总是要求所有的东西并且用户被呈现时 有“要么全有要么全无”的选择。

  • 向客户端添加检查存储/访问的资源的能力 管理界面。

联系人/支持

随时可以顺道访问“未承载”或“远程存储”频道 freenode IRC,你总能找到作者和 愿意帮助理解、设置和 解决任何问题。

邮件列表、推特和其他间接沟通渠道可以 也可以在Unhosted movement site上找到。

当然,还有github repository的公开问题。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java简明流语法处理用户输入   GoogleAppEngine Java中的计划电子邮件   java JDK目录未设置或无效(unity)?   java CountDownLatch会导致JFrame(JButtons等)中的内容消失,只有当鼠标悬停时才会返回   java如何将日期发送到游标?   在Java中执行groovy文件   与Oracle和Postgres兼容的java Spring数据类jpa查询   Google App Engine中的java“平台方法缺失”和“NoSuchMethod”错误   java无法到达请求映射端点,因此我收到404错误   mysql mysqldump在java中不起作用   java在spring mvc中如何将节点对象注入服务类?   尝试使用Java连接到mySQL服务器(工作台)时出错   JavaFX和MVP,对象在不应该被垃圾收集的时候被垃圾收集   java检查出生日期是否在3个整数中有效(mm/dd/yyyy)