使用具有不同应用程序名称的多个角色提供者时,如何防止重复的成员资格用户?
我有一个使用“/”默认应用程序名称的会员资格提供商。然后,我有多个共享此通用会员资格提供程序配置的应用程序。每个应用程序都有自己的角色提供程序配置,它们都与成员资格提供程序共享相同的数据库,但使用不同的应用程序名称来相互隔离其角色。
当我创建成员时,会创建一条用户记录,并因此在所有应用程序之间共享。然后,我创建每个应用程序独有的特定角色,因为它们使用不同的应用程序名称。
我遇到的问题是当我对已经存在的成员调用 Roles.AddUserToRole 时。角色提供者无法识别用户,因为成员资格和角色提供者的应用程序名称上下文不同,因此它会继续为角色所属的应用程序名称创建新的用户记录。
如何在成员资格和角色提供者之间不共享应用程序名称的情况下防止创建这些重复的用户记录?
I have a single membership provider which is using the '/' default application name. I then have multiple applications which share this common membership provider configuration. Each application has it's own role provider configuration, they all share the same database as the membership provider but use a different application name to isolate their roles from each other.
When I create a member then a single user record is created and hence shared across all the applications. I then create specific roles unique to each application as they use a different application name.
The problem I am having is when I call Roles.AddUserToRole on a member who already exists. The roleprovider does not recognise the user as the application name context of the membership and role providers are different and it therefore proceeds to create a new user record for the application name that the role belongs to.
How can I prevent these duplicate user records from being created without sharing the application name between the membership and role providers?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这些记录实际上并不是“重复的”。
了解提供者之间的关系和 aspnet_Users 表的角色可能有助于解决这个问题。
首先,要了解 MembershipProvider 和 RoleProvider 并不相互依赖,除了 MembershipProvider.DeleteUser() 方法中存在一些问题之外,我将在稍后对此进行解释。
成员资格的作用是对用户进行身份验证,并在身份验证的帮助下保护对资源的访问。
Roles的作用是通过角色分配来控制对资源的访问。
无论 aspnet_Users 的状态意味着什么,这是两个独立的问题并且不相关。
突出的问题是用于连接所有提供者的值是
username
。userid
guid 类似,如果所有提供程序都使用相同的应用程序名称,则只会为任何用户名创建一个 aspnet_users 记录,因为每个提供程序所做的第一件事就是检查 aspnet_users 是否匹配用户名和应用程序名称。如果找到,则使用它,如果没有,则创建一个并为该用户 ID 分配一个 guid。虽然 userId guid 可能看起来是“全局”标识符,但事实并非如此。
因此,有一个小警告 - 如果您知道接下来相关的问题,您可以通过为每个成员资格实例使用相同的应用程序名称并为每个角色实例使用不同的应用程序名称来使用具有公共成员资格存储的单独的角色提供程序。
我之前提到的对关注点分离的(非常愚蠢的)违反涉及调用 DeleteUser(deleteRelatedData) 时 SqlMembershipProvider 所采取的操作。然后,SqlMembershipProvider 就好像它是战斗中唯一的狗一样,跨角色和配置文件仅使用它的键删除记录,从而错过您希望消失的记录。
考虑:(这是使用前面提到的单一成员资格、多个角色的设置)
您创建具有成员资格的用户“John”,并使用角色为他分配一些角色。现在,您必须在 aspnet_users 中为 John 进行记录,一切都会顺利进行。 “John”是一名经理,并分配有适当的高级角色。
“约翰”由于某种原因成为“被解雇的人”,并通过会员资格被删除。如前所述,在我们独特的场景中,成员记录被删除,但角色信息保留。
雇用了一个新的“John”来接听电话,并为他创建了一个会员用户。
在业余时间,约翰探索了公司的内部网,他简直不敢相信自己能做这么多很酷的事情,作为一个傻瓜,他决定在人力资源模块给自己加薪。
你猜怎么着?由于孤立角色与“用户名”无关,新的“约翰”立即成为经理。
因此,这是您在决定利用(或者在本例中强制)内在的、经过充分测试和已知的提供程序堆栈时必须注意的“次要”警告。
我已经介绍了与此非常相似的场景,并提供了一个简单修改的概念证明,以消除此问题此处 和此处。
或者,您可以简单地意识到这一点并编写一些额外的代码来在删除用户时进行清理。
这两种选择都比实施定制提供商更具吸引力。
干杯,祝你好运。
The records are not actually 'duplicates'.
Understanding the relationship between the providers and the role of the aspnet_Users table may help clear this up.
First, understand that MembershipProvider and RoleProvider do not depend on one another, with a minor exception of some concern bleeding in the MembershipProvider.DeleteUser() method which I will explain later.
The role of Membership is to authenticate a user and, with the help of Authentication, protect access to your resources.
The role of Roles is to control access to resources by role assignment.
These are 2 seperate concerns and are not related, regardless of what the state of aspnet_Users may imply.
The salient issue is that the value that is used to connect all of the providers is
username
. Theuserid
guid is similar and only one aspnet_users record is created for any username if all providers use the same application name because the first thing each provider does is check aspnet_users for a matching username and application name. If it finds one, it uses it, if not, it creates one and assigns a guid to the userid.While it may appear that the userId guid is the 'global' identifier, this is not the case.
So, with a minor caveat - you can user separate role providers with a common membership store by using the same applicationname for each instance of membership and a different applicationname for each roles instance if you are aware of the issue related next.
The (really stupid) violation of the Seperation of Concerns that I mentioned earlier involves the actions taken by the SqlMembershipProvider when DeleteUser(deleteRelatedData) is called. It is then that SqlMembershipProvider acts as if it is the only dog in the fight, crosses over to roles and profiles to delete records using only it's keys and thus miss records that you expect to be gone.
Consider: (this is using the aforementioned setup of single membership, multiple roles)
You create user "John" with membership, assign him some roles with Roles. You now have to records in aspnet_users for John and everything works swimmingly. "John" is a manager and has appropriate high level roles assigned.
"John" becomes the 'fired guy' for some reason and is deleted via membership. As stated before, in our unique scenario, the membership records are deleted but the roles information remains.
A new "John" is hired to answer the phones and a membership user is created for him.
In his spare time, john explores the company intranet and can't believe how much cool stuff he can do and as a goof decides to give himself a raise in the HR module.
Guess what? new "John" is immediately a manager due to orphaned roles that are keyed off of "username".
So, that is the 'minor' caveat that you must be aware of when deciding to leverage, or in this case, coerce, the intrinsic, well tested and known provider stack.
I have already covered a scenario very similar to this and provide a proof of concept for a simple modification to eliminate this issue here and here .
Alternately, you can simply be aware of this and write some extra code to clean up when you delete a user.
Both of these are a far more attractive option than implementing custom providers.
Cheers and good luck.