跳转到主要内容

为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

  1. 我们查询一个实用工具,因此集成者可以注册一个钩子,使用自己的逻辑生成用户ID

    generator = queryUtility(IUserIdGenerator)
    if generator:
        userid = generator(data)
        if userid:
            data['user_id'] = userid
            return userid
  2. 如果use_uuid_as_userid在站点属性中设置,我们将生成一个uuid。这是此包引入的新属性,可以在安全控制面板中设置。

  3. 如果提供了用户名并且我们不使用电子邮件作为登录,则我们简单地将该用户名作为用户ID返回。

  4. 如果提供了全名,我们将基于全名创建一个用户ID,这可能会导致如“bob-jones-2”这样的ID。

当电子邮件地址用作登录名时,我们最初也将电子邮件地址用作用户ID。这有几个可能的缺点,这是新可插拔方法的主要原因

  • 它不适用于一些有效的电子邮件地址。

  • 以这种方式公开电子邮件地址可能不受欢迎。

  • 当用户稍后更改他的电子邮件地址时,用户ID仍然是他的旧地址。它有效,但可能令人困惑。

另一种可能性是简单地生成一个uuid,但这看起来不好。我们当然可以尝试这样做:这里的主要优点是,如果你以后删除了它,你不能创建具有相同用户ID的新用户。如果你得到相同的ID,这个新用户将得到相同的全局和本地角色,如果那些没有被清理。

当选择用户ID时,数据中的“user_id”键被设置,并返回用户ID。

这些更改旨在合并到“plone.app.users”中。

登录名的控制

类似地,定义了一个ILoginNameGenerator接口。

通常登录名和用户ID是相同的,但这并不一定正确。当使用电子邮件地址作为登录名时,我们可能有不同的用户ID,通过调用生成用户ID方法生成。

我们尝试一些选项来生成好的登录名

  1. 我们查询一个实用工具,因此集成者可以注册一个钩子,使用自己的逻辑生成登录名

    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
  2. 如果提供了用户名并且我们不使用电子邮件作为登录,则我们简单地将该用户名作为登录名返回。

  3. 当使用电子邮件作为登录时,我们使用电子邮件地址。

在所有情况下,如果定义了PAS.applyTransform,我们都会在登录名上调用它。这是PAS的最近添加功能,目前处于开发中。

当选择登录名时,数据中的“login_name”键被设置,并返回登录名。

这些更改旨在合并到“plone.app.users”中。

小写登录名

我们存储用户名时使用小写形式。电子邮件地址本身可以是大小写混合的,但这并不是设计初衷,而是一种(幸运的)情况。

这需要使用 Products.PluggableAuthServicemaurits-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.PlonePASZODBMutablePropertyProvider 添加了一个补丁,该补丁添加了两个新但为空的方法,这些方法是 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 (60.2 kB 查看哈希值)

上传时间 源代码

由以下支持