我有一个使用任意数量的成员资格提供程序的.Net应用程序。我不会理解这些原因,但我不希望这些原因得到预先配置,但我想以编程方式创建和添加它们。反正有没有这样做?我没有创建提供程序的问题,但Membership.Providers是只读的,所以我无法添加它们。
答案 0 :(得分:6)
迟到,迟到的答案,但你可以使用反思:
public static class ProviderUtil
{
static private FieldInfo providerCollectionReadOnlyField;
static ProviderUtil()
{
Type t = typeof(ProviderCollection);
providerCollectionReadOnlyField = t.GetField("_ReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
}
static public void AddTo(this ProviderBase provider, ProviderCollection pc)
{
bool prevValue = (bool)providerCollectionReadOnlyField.GetValue(pc);
if (prevValue)
providerCollectionReadOnlyField.SetValue(pc, false);
pc.Add(provider);
if (prevValue)
providerCollectionReadOnlyField.SetValue(pc, true);
}
}
然后,在您的代码中,您可以执行以下操作:
MyMembershipProvider provider = new MyMembershipProvider();
NameValueCollection config = new NameValueCollection();
// Configure your provider here. For example,
config["username"] = "myUsername";
config["password"] = "myPassword";
provider.Initialize("MyProvider", config);
// Add your provider to the membership provider list
provider.AddTo(Membership.Providers);
这是一个黑客攻击,因为我们使用反射来设置“_ReadOnly”私有字段,但它似乎有效。
以下是关于此问题的精彩帖子: http://elegantcode.com/2008/04/17/testing-a-membership-provider/
另一个好帖子: http://www.endswithsaurus.com/2010/03/inserting-membershipprovider-into.html
要特别注意在这些帖子中使用_ReadOnly的警告,因为您需要权衡操作只读集合的缺点与项目要求以及您要完成的任务。
此致
-Doug
答案 1 :(得分:1)
一个简单的方法是首先创建一个自定义成员资格提供程序(作为包装器)并将其挂钩在web.config中。然后,您实现此提供程序,以便能够根据真实成员资格提供程序列表对用户进行身份验证。
由于包装是由你拥有的,你只能受到想象力的限制。
答案 2 :(得分:0)
我知道它已经无关紧要,但对于未来的读者,我会为类似的问题添加我的解决方案。
我想创建一个可以在任何其他提供程序上添加一些功能的提供程序(装饰器模式),所以我想将内部提供程序添加到providers集合中(对于我上面的那个 - 它不起作用,因为如果提供者不在提供者集合中 - 它将无法创建用户。)
我不喜欢反射解决方案有两个原因:
显而易见的 - 它打破了封装。
第二个 - 代码应该在没有反射权限的情况下运行,否则,任何一段代码都可以添加自己的提供者 - 因此任何安全性都会受到损害。
我发现的(简单)解决方案是在web.config中注册两个提供程序,将默认提供程序设置为我的提供程序,并从提供程序集合中在运行时加载第二个提供程序。
对于第一个问题 - 如果您可以在运行时知道需要哪些提供程序,最好在web.config中注册它们,并且可能在运行时更改它们的属性。
另一个解决方案(仍然是“正确”,但速度很慢)是将安全检查委托给一个小exe,更改它的app.config,运行它,并将结果作为输出返回(您的提供商可以做这个)。 DPAPI可以为密码传递提供安全性。