Dolmen CMS认证包
项目描述
dolmen.app.authentication 是负责Dolmen应用程序中用户和组管理的包。它建立在 dolmen.authentication 和 zope.pluggableauth 之上,提供了一套插件和基类,有助于构建复杂的用户和组系统。
初始Grok导入
>>> import grok >>> from grokcore.component.testing import grok_component
凭证插件
>>> from zope.pluggableauth.interfaces import ICredentialsPlugin
凭证插件负责提取凭证,以便识别用户。 dolmen.app.authentication 提供了一个插件,即Cookies凭证。
认证插件
>>> from zope.pluggableauth.interfaces import IAuthenticatorPlugin
认证插件使用提取的凭据来检索和识别主体。 dolmen.app.authentication 提供了两个插件 - 全局注册表认证 & 主体文件夹认证
全局注册表认证
为了注册主体,zope.principalregistry 包提供了一个全局注册表,该注册表在每次启动时都不是持久的,并重新构建。全局注册表认证器旨在在该全局注册表中查找主体。
我们验证我们的实现是否符合要求
>>> from dolmen.app.authentication import plugins >>> IAuthenticatorPlugin.implementedBy(plugins.GlobalRegistryAuth) True >>> plugin = plugins.GlobalRegistryAuth() >>> verifyObject(IAuthenticatorPlugin, plugin) True
为了测试此插件,我们在全局注册表中注册了一个用户,称为“mgr”。我们将使用“mgr”凭据进行查找测试
>>> user = plugin.authenticateCredentials( ... {'login': u"mgr", "password": u"mgrpw"}) >>> print user <GlobalRegistryPrincipal "zope.mgr">
错误的凭据将使认证返回 None
>>> user = plugin.authenticateCredentials( ... {'login': u"mgr", "password": u"wrongpass"}) >>> user is None True >>> user = plugin.authenticateCredentials( ... {'login': u"anon", "password": u"wrongpass"}) >>> user is None True
无法单独获取主体信息
>>> print plugin.principalInfo('zope.mgr') None >>> print plugin.principalInfo('zorglub') None
主体文件夹认证
dolmen.app.authentication 引入了一个新的认证插件,用于存储和检索持久主体。此插件是一个容器,可以存储 IPrincipal 对象并按照 IAuthenticatorPlugin 的规定检索它们。
我们验证我们的实现是否符合要求
>>> from dolmen.app.authentication import plugins >>> IAuthenticatorPlugin.implementedBy(plugins.PrincipalFolderPlugin) True >>> plugin = plugins.PrincipalFolderPlugin() >>> verifyObject(IAuthenticatorPlugin, plugin) True
为了测试此插件,我们必须创建一个 IPrincipal 对象并将其存储在插件中。然后,我们可以进行查找测试。
为了使认证可插件化,主体认证插件依赖于 3 个接口
IAccountStatus:如果从 IPrincipal 对象存在到该接口的适配器,则使用它来确定主体是否可以登录。它允许禁用用户帐户并计算该禁用。
IPasswordChecker:此适配器用于检查凭据。如果不存在(或如果 IPrincipal 对象不提供此接口),则终止认证并返回 None。
IPrincipalInfo:与上一个插件不同,主体文件夹认证器不直接返回 PrincipalInfo 对象,而是使用适配器检索适当的主体信息对象。这是将特定行为插入我们的认证系统所必需的。
让我们首先实现一个基本的 IPrincipalObject。一旦存储,我们就可以开始查找和适配器实现
>>> from dolmen.app.authentication.tests import User
请参阅以下实现
from dolmen.authentication import IPrincipal from zope.interface import implements class User(object): implements(IPrincipal) def __init__(self, id, title=u"", desc=u""): self.id = id self.title = title or id self.description = desc self.groups = []
我们可以验证我们的实现是否符合接口
>>> from dolmen.authentication import IPrincipal >>> stilgar = User(u"stilgar") >>> verifyObject(IPrincipal, stilgar) True
我们可以为我们的 User 类设置一个简单的视图
>>> from grokcore.layout import Page >>> class UserView(Page): ... grok.name('index') ... grok.context(User) ... ... def render(self): ... return "<User %s>" % self.context.id >>> grok_component('index', UserView) True
实现是一致的。我们现在可以在插件容器中持久化主体
>>> plugin['stilgar'] = stilgar >>> print [user for user in plugin.keys()] [u'stilgar']
我们现在可以使用认证 API 尝试查找主体
>>> found = plugin.authenticateCredentials( ... {'login': 'stilgar', 'password': 'boo'}) >>> found is None True
主体未找到:我们没有可用的 IPasswordChecker 到 IPasswordChecker 的适配器,因此已终止认证过程。
提供适配器将使我们能够成功检索主体
>>> from dolmen.authentication import IPasswordChecker >>> class GrantingAccessOnBoo(grok.Adapter): ... grok.context(IPrincipal) ... grok.provides(IPasswordChecker) ... ... def checkPassword(self, pwd): ... if pwd == 'boo': ... return True >>> grok_component('booing', GrantingAccessOnBoo) True >>> found = plugin.authenticateCredentials( ... {'login': 'stilgar', 'password': 'boo'}) >>> found is not None True
当然,提供错误的密码将返回 None
>>> found = plugin.authenticateCredentials( ... {'login': 'stilgar', 'password': 'not boo'}) >>> found is None True
我们还可以通过其 ID 查找主体
>>> print plugin.principalInfo('stilgar') <dolmen.authentication.principal.LocatablePrincipalInfo ...> >>> print plugin.principalInfo("unknown") None
如前所述,可以通过 IAccountStatus 接口打开和关闭特定用户的登录能力
>>> from dolmen.authentication import IAccountStatus >>> class AllowLogin(grok.Adapter): ... grok.context(IPrincipal) ... grok.provides(IAccountStatus) ... ... @property ... def status(self): ... return "No status information available" ... ... def check(self): ... if self.context.id != "stilgar": ... return True ... return False >>> grok_component('allow', AllowLogin) True
在此示例中,我们明确禁止使用标识符“stilgar”的用户通过登录检索
>>> found = plugin.authenticateCredentials( ... {'login': 'stilgar', 'password': 'boo'}) >>> found is None True
设置站点
为了测试包的高级功能,我们将设置一个熟悉的环境。这样做,我们可以在真实 Dolmen 站点上下文中测试我们的包的行为
>>> from dolmen.app.site import Dolmen >>> root = getRootFolder() >>> site = Dolmen() >>> grok.notify(grok.ObjectCreatedEvent(site)) >>> root['site'] = site >>> from zope.authentication.interfaces import IAuthentication >>> from zope.pluggableauth import PluggableAuthentication >>> from dolmen.app.authentication import initialize_pau >>> PAU = PluggableAuthentication() >>> len(PAU.authenticatorPlugins) 0 >>> len(PAU.credentialsPlugins) 0 >>> initialize_pau(PAU) >>> print PAU.authenticatorPlugins ('globalregistry',) >>> print PAU.credentialsPlugins ('cookies', 'No Challenge if Authenticated') >>> site['auth'] = PAU >>> lsm = site.getSiteManager() >>> lsm.registerUtility(PAU, IAuthentication) >>> from grokcore.layout import Layout >>> from zope.interface import Interface >>> class Layout(Layout): ... grok.name('') ... grok.context(Interface) ... ... def render(self): ... return u'' ... ... def __call__(self, view): ... return u"<!DOCTYPE html>\n" + unicode(view.render()) >>> grok_component('layout', Layout) True >>> from dolmen.forms import crud >>> class Edit(crud.Edit): ... grok.context(Dolmen) ... grok.require('test.Edit') >>> grok_component('editsite', Edit) True >>> class DolmenIndex(Page): ... grok.name('index') ... grok.context(Dolmen) ... ... def render(self): ... return "Homepage" >>> grok_component('indexsite', DolmenIndex) True
登录
登录页面
为了获取正确的凭据,我们可以简单地使用 dolmen.app.authentication 提供的登录表单登录
>>> browser.open('http://localhost/site/@@login') >>> loginpage = browser.contents >>> 'id="login"' in loginpage True >>> 'id="password"' in loginpage True >>> browser.getControl('Username').value = 'mgr' >>> browser.getControl('Password').value = 'mgrpw' >>> browser.getControl('Log in').click() >>> browser.url 'http://localhost/site'
管理认证插件
dolmen.app.authentication 提供了一种启用和禁用不同认证插件的方法。
为了保持网站中的元素整洁,dolmen.app.authentication 假设认证插件持久保存在 PAU 容器中。
让我们用一个 PrincipalFolder 插件来举一个具体的例子
>>> members = plugins.PrincipalFolderPlugin() >>> grok.notify(grok.ObjectCreatedEvent(members)) >>> PAU['members'] = members
此时,主文件夹已创建并持久化。我们注意到,文件夹是在PAU实用容器内部创建的。
此时,我们可以访问管理视图
>>> browser.open("http://localhost/site/auth/@@authenticators") >>> print browser.contents <!DOCTYPE html> <form action="http://localhost/site/auth/@@authenticators" method="post" enctype="multipart/form-data"> <h1>Edit the authentication sources</h1> ...
“成员”主文件夹尚未激活。
让我们在其中创建一个用户对象
>>> chani = User(u"chani", title=u"Sihaya") >>> PAU['members']['chani'] = chani
现在,让我们用一个新的浏览器尝试登录
>>> new_browser = Browser() >>> new_browser.open('http://localhost/site/@@login') >>> new_browser.getControl('Username').value = 'chani' >>> new_browser.getControl('Password').value = 'boo' >>> new_browser.getControl('Log in').click() >>> "Login failed" in new_browser.contents True
使用管理视图机制,我们可以激活我们的主文件夹
>>> from dolmen.app.authentication.browser import management >>> adapter = management.IActiveFolders(PAU) >>> adapter.activeFolders () >>> adapter.activeFolders = (u'members',)
主文件夹现在已激活。让我们重试登录
>>> new_browser = Browser() >>> new_browser.handleErrors = False >>> new_browser.open('http://localhost/site/@@login') >>> new_browser.getControl('Username').value = 'chani' >>> new_browser.getControl('Password').value = 'boo' >>> new_browser.getControl('Log in').click() >>> "Login failed" in new_browser.contents False >>> print new_browser.url http://localhost/site
创建角色
>>> class Editor(grok.Role): ... grok.name('testEditor') ... grok.title(u"Editor") ... grok.description(u"A basic editor.") ... grok.permissions('test.Edit')>>> grok_component('editor', Editor) True
管理用户
用户可以被赋予角色。这可以通过一个视图实现,用户作为上下文
>>> browser.handleErrors = False >>> browser.open("http://localhost/site/auth/members/chani/@@grant_roles") >>> browser.getControl(name='form.field.roles').value = ['testEditor'] >>> browser.handleErrors = False >>> browser.getControl('Update').click()
这个视图是通过适配器实现的,可以在任何IPrincipals上使用。让我们检查我们之前的行为是否已经完成
>>> from zope.component.hooks import setSite >>> setSite(site) # we got to the context of our site >>> from dolmen.app.authentication.browser import roles >>> role_controller = roles.IPrincipalRoles(chani) >>> role_controller.roles set([u'testEditor'])
选定的角色已经存在。我们可以非常容易地修改它们
>>> role_controller.roles = [u'testEditor'] >>> role_controller.roles set([u'testEditor'])
角色管理在站点对象本身上应用更改。让我们验证角色是否已正确应用
>>> from zope.securitypolicy.interfaces import IPrincipalRoleManager >>> prm = IPrincipalRoleManager(site) >>> print prm.getRolesForPrincipal(chani.id) [(u'testEditor', PermissionSetting: Allow)]
注销
我们还可以通过调用注销页面手动销毁cookie
>>> 'dolmen.authcookie' in browser.cookies.keys() True >>> browser.open("http://localhost/site/@@logoutaction") >>> 'dolmen.authcookie' in browser.cookies.keys() False >>> browser.url 'http://localhost/site/logout.html'
更改
1.1.1 (2013-11-11)
修复了cookie编码错误。
1.1 (2013-11-06)
移除了所有dolmen.app依赖项,以便从无用的绑定中解放包。这是通过删除菜单条目和基本模式的集成来实现的。
1.0b4(2013-10-31)
PrincipalFolderPlugin需要标题。
修正了cookie值的解码。
1.0b3(2010-11-18)
在管理视图中修正了词汇表的声明方式(角色授权和用户文件夹选择。存在可插拔性,但如果找不到组件,则不会返回基本词汇表。
1.0b2(2010-11-16)
IChangePassword的变化。密码现在可以是普通字符串或unicode值(通过IProtected)。IChangePassword随后为表单提供模式。请参阅dolmen.authentication中的相应更改。
GlobalRegistry插件已被修复。它将不再触发AuthenticatedPrincipalCreated事件。这解决了重要错误:事件的处理器曾经认为GlobalRegistry中的所有主体都是认证的,即使是未认证的。
1.0b1(2010-07-28)
国际化代码并添加了法语翻译。
修正了角色授权UI并通过上下文标签公开。
改进了测试覆盖率。
1.0a3(2010-06-25)
GlobalRegistry插件在principalInfo未找到时不再引发错误。相反,它返回None,如IAuthentication所指定。已添加测试以修复该行为和PrincipalFolder的行为。
1.0a2(2010-06-25)
当principalInfo未找到时,PrincipalFolder不再引发错误。相反,它返回None,如IAuthentication所指定。
1.0a1(2010-06-04)
删除了未使用和不合理的权限:“CanLogin”和“CanLogout”。
dolmen.app.authentication现在使用dolmen.menu创建菜单和注册条目。
我们现在使用zeam.form表单库而不是z3c.form。
0.1.1 (2010-05-31)
更新了翻译。
0.1 (2010-05-30)
初始发布。
项目详情
下载文件
下载适用于您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。
源分发
dolmen.app.authentication-1.1.1.tar.gz的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 0a75c1167c7e26c60bddb2ca123b511b15f52368c4d1c7f62268bf9069aa96fc |
|
MD5 | 22cb5beae1c3d5dec6833944e2f23fc5 |
|
BLAKE2b-256 | bbf0ec7a4fbf12409c47ed044ed708579214a5ad97f1f205e4d62ef7399ea6d8 |