为Plone 4提供的Emaillogin修复
项目描述
简介
自从Plone 4.0以来,您可以通过在安全控制面板中设置来配置Plone,允许用户使用他们的电子邮件地址登录。这可以正常工作。但一些改进将很有用,在将其添加到核心Plone之前需要更仔细的考虑。这就是这个包的作用。
这是一个临时包,包含一些修复,用于您想要在Plone 4中将用户的电子邮件地址用作登录名时。它还引入了一些挂钩,用于确定新用户的用户ID和登录名。
Plone版本
此包已在Plone 4.1、4.2和4.3上进行测试。它不能在4.0上工作。
对于Plone 3,您必须使用collective.emaillogin包。
依赖关系
我们需要一个比最新Plone版本中可用的版本更新的Products.PluggableAuthService版本。假设您正在使用buildout为您的Plone站点,您需要向版本部分添加一行
Products.PluggableAuthService = 1.10.0
任何比这版本更新的版本都行。如果你的Plone版本已经包含了这个版本或更新的版本,则不需要添加此行。
这个包是做什么的?
用户ID和登录名之间更清晰的分离
注册浏览器视图的验证使用两种方法来获取用户ID和登录名
# Generate a nice user id and store that in the data. user_id = self.generate_user_id(data) # Generate a nice login name and store that in the data. login_name = self.generate_login_name(data)
之后,数据字典将会有相应的键“user_id”和“login_name”。
我们尽量避免使用“username”作为变量,因为没有人知道它是指用户ID还是登录名。在标准Plone中这始终相同,但这不一定正确,尤其是在使用电子邮件地址作为登录名时。
这些更改旨在合并到“plone.app.users”中。
用户ID的控制
定义了一个IUserIdGenerator接口。这用于注册浏览器视图中的新generate_user_id方法(也用于作为管理员添加新用户时)。两个示例实现
def uuid_userid_generator(data=None):
# Return a uuid, independent of the data.
# This is available in utils.py in the plone.app.users patches.
from zope.component import getUtility
from plone.uuid.interfaces import IUUIDGenerator
generator = getUtility(IUUIDGenerator)
return generator()
def login_name_as_userid_generator(data):
# We like to keep it simple.
return data.get('username')
在generate_user_id中,我们尝试一些选项来生成好的用户ID
我们查询一个实用工具,因此集成者可以注册一个钩子,使用自己的逻辑生成用户ID
generator = queryUtility(IUserIdGenerator) if generator: userid = generator(data) if userid: data['user_id'] = userid return userid如果use_uuid_as_userid在站点属性中设置,我们将生成一个uuid。这是此包引入的新属性,可以在安全控制面板中设置。
如果提供了用户名并且我们不使用电子邮件作为登录,则我们简单地将该用户名作为用户ID返回。
如果提供了全名,我们将基于全名创建一个用户ID,这可能会导致如“bob-jones-2”这样的ID。
当电子邮件地址用作登录名时,我们最初也将电子邮件地址用作用户ID。这有几个可能的缺点,这是新可插拔方法的主要原因
它不适用于一些有效的电子邮件地址。
以这种方式公开电子邮件地址可能不受欢迎。
当用户稍后更改他的电子邮件地址时,用户ID仍然是他的旧地址。它有效,但可能令人困惑。
另一种可能性是简单地生成一个uuid,但这看起来不好。我们当然可以尝试这样做:这里的主要优点是,如果你以后删除了它,你不能创建具有相同用户ID的新用户。如果你得到相同的ID,这个新用户将得到相同的全局和本地角色,如果那些没有被清理。
当选择用户ID时,数据中的“user_id”键被设置,并返回用户ID。
这些更改旨在合并到“plone.app.users”中。
登录名的控制
类似地,定义了一个ILoginNameGenerator接口。
通常登录名和用户ID是相同的,但这并不一定正确。当使用电子邮件地址作为登录名时,我们可能有不同的用户ID,通过调用生成用户ID方法生成。
我们尝试一些选项来生成好的登录名
我们查询一个实用工具,因此集成者可以注册一个钩子,使用自己的逻辑生成登录名
pas = getToolByName(self.context, 'acl_users') generator = queryUtility(ILoginNameGenerator) if generator: login_name = generator(data) if login_name: login_name = pas.applyTransform(login_name) data['login_name'] = login_name return login_name如果提供了用户名并且我们不使用电子邮件作为登录,则我们简单地将该用户名作为登录名返回。
当使用电子邮件作为登录时,我们使用电子邮件地址。
在所有情况下,如果定义了PAS.applyTransform,我们都会在登录名上调用它。这是PAS的最近添加功能,目前处于开发中。
当选择登录名时,数据中的“login_name”键被设置,并返回登录名。
这些更改旨在合并到“plone.app.users”中。
小写登录名
我们存储用户名时使用小写形式。电子邮件地址本身可以是大小写混合的,但这并不是设计初衷,而是一种(幸运的)情况。
这需要使用 Products.PluggableAuthService 的 maurits-login-transform 分支。该分支引入了一个属性 login_transform。将此属性设置为 lower 时,PAS 会调用 lower 方法,该方法会在提供登录名时被调用。
在 plone.app.users 中的所有相关位置都已更改为考虑这个新属性,使用类似下面的代码:
login_name = pas.loginTransform(login_name)
在 plone.app.controlpanel 的安全面板中,我们将 set_use_email_as_login 方法更改为在启用电子邮件作为登录名时将 login_transform 设置为小写。出于安全考虑,我们永远不会将其更改为默认的空字符串。这对于正常的非电子邮件登录名来说也是可以的。
注意,当 login_transform 设置为 lower 时,最终用户可以使用大写 JOE 登录,然后将被登录为登录名 joe,当然前提是密码正确。如果您仍然有大小写混合的登录名,则无法登录。
将 login_transform 设置为非空字符串将自动将此转换应用于数据库中所有现有的登录。
注意:当此功能合并到核心 Plone 中时,登录名将不会默认转换为小写。此选项将仅当网站管理员需要时才可用。启用电子邮件作为登录名也将启用小写登录名。
更新登录名
我们为 Products.PlonePAS 的 ZODBMutablePropertyProvider 添加了一个补丁,该补丁添加了两个新但为空的方法,这些方法是 PAS 更改后的 IUserEnumerationPlugin 接口所需。
def updateUser(self, user_id, login_name): pass def updateEveryLoginName(self, quit_on_first_error=True): pass
这已被合并到 Products.PlonePAS 中。
控制面板
在安全面板中开启或关闭电子邮件作为登录名时,现在将自动更新现有的登录名。如果有重复项,可能会失败。
以前在 @@migrate-to-emaillogin 视图(类 EmailView)中执行现有用户的更新操作,该视图来自 plone.app.controlpanel。我们已经简化了这个页面,使其只搜索重复的登录名。您可以搜索重复的电子邮件地址或重复的用户 ID,总是小写。
安全面板现在有一个选项 使用 UUID 用户 ID,默认情况下是关闭的。
设置自己的登录名
简化了 Products.CMFPlone.utils.set_own_login_name 方法,大部分之前的代码都被移动到了 PAS 本身。
def set_own_login_name(member, loginname):
"""Allow the user to set his/her own login name.
If you have the Manage Users permission, you can update the login
name of another member too, though the name of this function is a
bit weird then. Historical accident.
"""
pas = getToolByName(member, 'acl_users')
mt = getToolByName(member, 'portal_membership')
if member.getId() == mt.getAuthenticatedMember().getId():
pas.updateOwnLoginName(loginname)
return
secman = getSecurityManager()
if not secman.checkPermission(ManageUsers, member):
raise Unauthorized('You can only change your OWN login name.')
pas.updateLoginName(member.getId(), loginname)
安装
在附加组件控制面板中安装此插件时,将执行以下操作。
它添加了 use_uuid_as_userid 站点属性,默认值为 False。
如果站点已经使用电子邮件作为登录名,我们将 login_transform 设置为 lower。这可能会导致错误并退出安装。我们可能想要捕获这个错误并仅记录一个警告。
它明确启用了电子邮件作为登录名。在将此包合并回核心 Plone 时,不会这样做。
变更日志
1.3 (2013-02-19)
依赖于最近发布的 Products.PluggableAuthService >= 1.10.0。[maurits]
1.2 (2013-01-23)
确保用户 ID 是字符串,而不是 Unicode。[maurits]
1.1 (2013-01-23)
确保在 set_own_login_name 中检查了“管理用户”权限。[maurits]
1.0 (2013-01-22)
初始发布
项目详情
collective.emaillogin4-1.3.zip的哈希值
| 算法 | 哈希摘要 | |
|---|---|---|
| SHA256 | ea257d99d8cc88229ccde98f35e97faafb35560ef7d343f38c76588fd4c4a77b |
|
| MD5 | b296e58d1e6b20b395e71ce221ac76f2 |
|
| BLAKE2b-256 | 9a80ba37ee2963128c18454a7f644d96173e6098c57bbb57e3c5a166e7192533 |