【问题标题】:How to fine tune a Membership Provider?如何微调会员提供者?
【发布时间】:2010-04-30 16:38:23
【问题描述】:

在我上一个 question about fine-tuning 的所有答案都比我预期的更有用之后,我想我也会问另一个关于 MembershipProviders 的类似问题。

好的,首先要澄清一下:我知道什么是会员、角色和个人资料提供者,如何实现我自己的,如何配置它们,以及关于它们的大部分内容。
实现角色和配置文件提供者非常简单,因为它们大多数时候只需要简单的 CRUD。 (对于 RoleProvider 的大约一半方法而言,一行 LINQ 就足够了。)

但是,会员资格提供者是另类的野兽。你们中的许多人可能意识到它违反了 SR(单一责任)原则,因为它必须做与用户管理相关的所有事情。虽然这为自定义留下了很大的空间,但它也有其缺点。 Internet 上没有关于它们的确切预期行为是什么的信息,例如它们应该何时抛出异常或简单地返回 null 等等。

我使用this sample implementation作为参考,但它也包含一些矛盾。

  • 例如,它使用自己的 ValidateUser 方法检查 ChangePassword 方法中的凭据。但 ValidateUser 还将用户的 LastLoginDate 更新为当前日期。那么,框架是否希望我也将其设置在我自己的提供程序中,还是只是示例中的错误?
  • 另一个是:ChangePassword方法每次验证新密码时都会抛出异常,而CreateUser从不抛出异常,它只是返回false。
  • 最后但并非最不重要的一点是:它会计算用户的无效密码尝试次数,并在超过阈值时将其锁定。虽然这很好,但它需要手动操作来解锁用户。如果我的提供商在一定时间后自动解锁用户是否有问题?

  • (EDIT) 我差点忘了:示例中的 CreateUser 方法从方法参数中插入了 ID。我实际上认为这是不好的做法,因为我使用带有自动 incement 的 inters 作为 ID,所以从某个方法参数插入它们不是一种选择。我应该忽略该参数,还是要求其值为 null 并在不是时抛出异常?

总而言之,ASP.NET 对 MembershipProvider 的行为有任何假设吗?
是否有任何文档描述了我应该何时抛出异常或只返回 null?

我还试图找到一组通用单元测试,它们可以为预期的行为提供一些指导,但是没有运气,我找到了很多关于“单元测试很好”和“如何对 MembershipProvider 进行单元测试”的文章,但不会有任何实际测试。

提前感谢大家!

【问题讨论】:

    标签: .net asp.net asp.net-membership membership-provider custom-membershipprovider


    【解决方案1】:

    您可以咨询 MSDN 以获得指导。例如,RoleProvider.RemoveUsersFromRoles 提供以下指导:

    RemoveUsersFromRoles 由 RemoveUserFromRole , RemoveUsersFromRole , RemoveUserFromRoles 和 RemoveUsersFromRoles 方法的 删除指定的角色类 来自指定角色的用户 数据源。只有角色 配置的应用程序名称是 修改。

    如果任何指定的角色名称是 未找到配置的 应用程序名称,我们建议 您的提供商抛出一个 提供者异常。

    如果任何指定的用户名是 不与任何 指定的角色名称 配置了applicationName,我们 建议您的提供商抛出一个 提供者异常。

    如果任何指定的用户名是 null 或者是一个空字符串,我们 建议您的提供商抛出一个 例外。

    如果任何指定的角色名称是 null 或者是一个空字符串,我们 建议您的提供商抛出一个 例外。

    如果您的数据源支持 交易,我们建议您 将每个删除操作包含在 事务并且您回滚 事务并抛出异常,如果 任何删除操作都会失败。

    RoleProvider.GetRolesForUser 说:

    GetRolesForUser 由 Roles 类的 GetRolesForUser 方法调用,以从数据源中检索与指定用户关联的角色名称。仅检索配置的 ApplicationName 的角色。

    如果配置的 applicationName 的指定用户不存在任何角色,我们建议您的提供程序返回一个不包含任何元素的字符串数组。

    如果指定的用户名为 null 或为空字符串,我们建议您的提供程序抛出异常。

    但是,在实践中,每个提供程序中只有少数方法和行为是必需的和预期的。其余的是对您希望实现的功能的支持。

    在处理默认提供程序堆栈几年后,我开始了解一些让您对链接到的示例犹豫不决的事情,这是一个非常简单的实现,例如在 ChangePassword 中方法。

    如果您使用反射器并检查 SqlMembershipProvider,您会发现一些显着差异...

    例如:

    • ValidateUser 更新登录日期,因为用户正在登录,它通过调用 .CheckPassword 并为 UpdateLastLoginTime 设置 true。更改密码调用相同的方法,但提供错误。

    • CreateUser 方法接受 ProviderUserKey,因为 SPROC 也将接受 UserId 参数。这是为了允许在成员表和用户表之间重新创建和同步。作为 API 的使用者,您通常不会使用此功能,但提供程序堆栈会在内部使用。

    • 关于锁定.. 由您决定。这就是实现自定义提供程序的全部内容:获得您想要的行为。正如我所说,系统要求很少。

    所以,这将我们带到您问题的最后一部分(两段都提到了同样的问题):预期行为和单元测试...

    由于提供者的行为在很大程度上是任意的,并且预期的行为很少,因此一组已建立的通用测试将包含很少的方法。您需要编写适用于您的实现行为的测试。

    作为最后一点,我建议您使用 find 和 download Asp.Net 提供程序工具包示例。它为您提供了完整的 Sql 提供程序堆栈的工作源代码,并将让您深入了解“真正的”提供程序是如何实现的。

    事后思考:

    此时,我正在实现一个与默认 Sql 堆栈 100% 兼容的完整 SQLite 提供程序堆栈。测试套件验证我的堆栈和 asp.net 之间的行为奇偶性。如果您通过我的个人资料访问我的博客并与我联系,我会在测试完成时通知您,您可以将它们用作基准,了解默认堆栈的确切预期。

    【讨论】:

    • +1。感谢您的回答。但是,您遗漏了最重要的部分。我应该在哪些方法中抛出异常,在哪些方法中我应该只返回 false(或 null,如果适用)?
    • @Venemo - 我更新了答案,为您提供您所要求的“正式”指导以及主观指导。
    • 非常感谢,这正是我想要的。 :) 我不知道 MSDN 有这么权威的指南。 (哦,如果您不介意,我会在您的博客上与您联系。)
    猜你喜欢
    • 2010-10-28
    • 1970-01-01
    • 1970-01-01
    • 2013-09-26
    • 2011-04-26
    • 1970-01-01
    相关资源
    最近更新 更多