这些记录实际上并不是“重复的”。
了解提供者之间的关系和 aspnet_Users 表的角色可能有助于弄清楚这一点。
首先,要了解 MembershipProvider 和 RoleProvider 不相互依赖,除了一点点例外,在 MembershipProvider.DeleteUser() 方法中存在一些问题,我将在后面解释。
Membership 的作用是对用户进行身份验证,并在身份验证的帮助下保护对资源的访问。
Roles 的作用是通过角色分配来控制对资源的访问。
无论 aspnet_Users 的状态可能暗示什么,这些都是 2 个独立的问题并且不相关。
突出的问题是用于连接所有提供者的值是username
. guid 类似,如果所有提供程序使用相同的应用程序名称,userid
则只会为任何用户名创建一个 aspnet_users 记录,因为每个提供程序所做的第一件事是检查 aspnet_users 以查找匹配的用户名和应用程序名称。如果它找到一个,它会使用它,如果没有,它会创建一个并将一个 guid 分配给用户 ID。
虽然看起来 userId guid 是“全局”标识符,但事实并非如此。
因此,有一点需要注意 - 如果您知道接下来相关的问题,您可以通过对每个成员资格实例使用相同的应用程序名称和为每个角色实例使用不同的应用程序名称来使用具有公共成员资格存储的单独角色提供程序。
我之前提到的(非常愚蠢的)对关注点分离的违反涉及调用 DeleteUser(deleteRelatedData) 时 SqlMembershipProvider 采取的操作。然后 SqlMembershipProvider 就好像它是战斗中唯一的狗一样,跨越角色和配置文件以仅使用它的键删除记录,从而错过您希望消失的记录。
考虑:(这是使用前面提到的单个成员、多个角色的设置)
您创建具有成员资格的用户“John”,为他分配一些具有角色的角色。您现在必须在 aspnet_users 中为 John 记录,并且一切正常。“John”是一名经理,并分配了适当的高级角色。
“约翰”由于某种原因成为“被解雇的人”,并通过会员资格被删除。如前所述,在我们独特的场景中,成员记录被删除,但角色信息仍然存在。
雇用了一个新的“约翰”来接听电话,并为他创建了一个会员用户。
在业余时间,john 浏览了公司的内部网,简直不敢相信他能做多少很酷的事情,作为一个傻瓜,他决定在 HR 模块中给自己加薪。
你猜怎么了?新的“John”由于与“用户名”键控的孤立角色而立即成为经理。
因此,这是您在决定利用或在这种情况下强制使用内在的、经过良好测试且已知的提供程序堆栈时必须注意的“次要”警告。
我已经介绍了一个与此非常相似的场景,并提供了一个概念证明,可以通过简单的修改来消除这里 和 这里的这个问题。
或者,您可以简单地意识到这一点并编写一些额外的代码来在删除用户时进行清理。
这两者都是比实现自定义提供程序更具吸引力的选择。
干杯和好运。