【问题标题】:Switch to SQL membership provider from AD membership provider runtime从 AD 成员资格提供程序运行时切换到 SQL 成员资格提供程序
【发布时间】:2011-11-04 20:23:38
【问题描述】:

在我的 asp.net 应用程序管理功能中,我试图结合 AD 身份验证和表单授权来创建用户、角色和将用户分配给角色等。我已经在我的 web.config 中配置了 MembershipADProvider 和 AspNetSqlMembershipProvider,其中 MembershipADProvider 作为默认一个。用户使用 AD 身份验证登录后,我需要切换/分配我的成员资格对象以使用 AspNetSqlMembershipProvider 以便从成员资格对象(来自 dbo.aspnet_Users 表)中获取所有用户。如何在运行时切换提供程序?搜索此问题后,我尝试了不同的方法,但到目前为止,这些方法似乎都不适合我。 以下是我尝试的几种方法: 1. foreach(MembershipProvider mp在Membership.Providers) { if (mp.Name == "MembershipADProvider") { Membership.Providers.Remove(MembershipADProvider");
MembershipUserCollection 用户 = Membership.GetAllUsers(); ddlUsers.DataSource = 用户; ddlUsers.DataBind();
休息; } }

Membership.Providers.Remove(MembershipADProvider"); - 不起作用,因为它不受支持.. 另外,尝试清除 Membership.Providers,然后只添加同样不受支持的 AspNetSqlMembershipProvider 类型。

  1. 我无法设置 Membership.Provider 的值来自 Membership.Providers["AspNetSqlMembershipProvider"] as Membership.Provider 是只读属性。

  2. 我尝试在 2 个提供程序之间切换连接字符串,但没有切换提供程序,因为两者都是不同类型的提供程序。如果两者都是 sqlserver 提供程序,我相信这会起作用。

请让我知道是否有人已成功实施,或者这是否是一种合理的方法。谢谢!

【问题讨论】:

    标签: asp.net membership provider


    【解决方案1】:

    您可以将显式提供程序传递给您的代码,而不是直接依赖于 Memebership(它只是包装了在配置中标记为默认值的那个)。无需在运行时交换它们,想想这会如何影响线程安全。

    因此,与其说Membership.GetAllUsers();,不如说(我手头没有编译器):

    public UserSerivce : IUserService
    {
       private MembershipProvider provider;
    
       public UserService(MembershipProvider provider)
       {
           this.provider = provider;
       }
    
       public IEnumerable<MembershipUser> GetUsers()
       {
           return provider.GetAllUsers();
       }
    
       public void DoSomethingElseUseful()
       {
           ...
       }
    
    }
    

    然后将其用于特定的提供者:

    var service = new UserService(Membership.Providers["mySqlMembershipProvider"]);
    var users = service.GetUsers();
    

    或者如果使用 AD 特定代码:

    var service = new UserService(Membership.Providers["myADMembershipProvider"]);
    var users = service.GetUsers();
    

    以这种方式使用 DI 也有助于保持代码的可测试性。

    【讨论】:

    • 感谢您的回复,TheCodeKing!这种方法看起来更干净,一旦它起作用。我之前确实尝试过引用特定的提供者(在类中,而不是服务方法中),例如 - Membership.Providers["ASPNetSqlRoleProvider"].GetAllUsers() - 但 Provider.GetAllUsers() 需要诸如 int pageIndex、int pageSize、出 int totalRecords。 Membership.GetAllUsers() 调用没有参数的基本函数。我尝试传递 Provider.GetAllUsers(1, 1, out val) 之类的参数,但没有成功。对此有什么想法吗?
    • 如果您查看反射器Membership.GetAllUsers(),只需致电Membership.GetAllUsers(0, 2147483647, out num)。出于性能原因,尝试加载所有用户可能不是一个好主意。最好对结果进行分页。
    • 我之前确实在反射器中查看了会员对象的 GetAllUsers(),是的,它确实调用了 Membership.GetAllUsers(0, 2147483647, out num)。使用确切的代码拨打电话并没有让我感到震惊。现在,在您再次指出之后,我尝试使用 users = Membership.Providers["AspNetSqlMembershipProvider"].GetAllUsers(0, 2147483647, out val);它奏效了!可以使用参数(0、2147483647、out val)调用吗?但是,这确实有效!谢谢!
    【解决方案2】:

    如果您只需要 aspnet_Users 表中的用户列表,只需使用 System.Data.SqlClient 对象连接到您的数据库并查询该表。没有理由(您提到的)您需要使用会员提供者来获取该数据。

    话虽如此,您的会员资格/身份验证方案听起来可能存在一些设计问题,也许最好在不同的问题中解决,但我认为如果您寻求对您想要完成的总体目标的评论,它可能对您有用与多个会员提供商。

    编辑:我发现了一些关于使用多个会员提供商的潜在有用的帖子。看起来总体思路是在您的Login 控件上实现处理Login.Authenticate 事件的自定义代码,并使用Membership.Providers["ProviderName"].ValidateUser 尝试对每个提供者进行身份验证。

    http://www.stevideter.com/2008/03/20/using-two-membership-providers-for-aspnet-logins/ http://forums.asp.net/p/1112089/1714276.aspx

    【讨论】:

    • 感谢您的快速回复!我同意,我可以使用 System.Data.SqlClient 并查询表来填充用户列表。但是,我试图使用 sqlserver 提供程序来实现这一点,以节省一些工作..但如果这根本不可能,那么我可能不得不走那条路。另外,如果我只使用 sqlserver 提供程序进行登录以及管理功能,那么我也可以实现这一点。
    • 感谢您的链接,我想我之前查找过类似的内容,其中谈到了使用这两个提供者的身份验证,这比较容易。我之前尝试过这种方法,即 MembershipProvider userProvider = Membership.Providers["ASPNetSqlRoleProvider"]; userProvider.GetAllUsers(1, 1, out val);这没有用。
    猜你喜欢
    • 2013-11-04
    • 1970-01-01
    • 1970-01-01
    • 2010-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-20
    相关资源
    最近更新 更多