我有一个使用任意数量的会员提供者的.Net 应用程序。我不会详细说明原因,但我不希望这些被预先配置,但我想以编程方式创建和添加它们。有没有办法做到这一点?我创建提供者没有问题,但 Membership.Providers 是只读的,所以我不能添加它们。
3 回答
迟到的答案,但您可以使用反射:
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);
这是一个 hack,因为我们使用反射来设置“_ReadOnly”私有字段,但它似乎工作。
这是一个关于这个问题的好帖子:http: //elegantcode.com/2008/04/17/testing-a-membership-provider/
另一个好帖子: http ://www.endswithsaurus.com/2010/03/inserting-membershipprovider-into.html
请特别注意在这些帖子中使用 _ReadOnly 的警告,因为您需要权衡操作只读集合与您的项目要求以及您要完成的工作的缺点。
问候,
-道格
一个简单的技巧是首先创建一个自定义成员资格提供程序(作为包装器)并将其挂接到 web.config 中。然后,您实现此提供者,以便能够根据真实成员提供者列表对用户进行身份验证。
由于包装器归您所有,您只受您的想象力的限制。
我知道它已经无关紧要,但对于未来的读者,我会为类似的问题添加我的解决方案。
我想创建可以在任何其他提供者(装饰器模式)上添加一些功能的提供者,所以我想将内部提供者添加到提供者集合中(对于我上面的那个 - 它不起作用,因为如果提供者不在 providers 集合中——它将无法创建用户)。
我不喜欢反射解决方案有两个原因:
显而易见的 - 它打破了封装。
第二个——代码应该在没有反射权限的情况下运行,否则,任何一段代码都可以添加自己的提供者——因此任何安全性都会受到损害。
我发现的(简单)解决方案是在 web.config 中注册两个提供程序,将默认提供程序设置为我的提供程序,并在运行时从提供程序集合中加载第二个提供程序。
对于第一个问题 - 如果您可以在运行前知道需要哪些提供程序,最好在 web.config 中注册它们,并可能在运行时更改它们的属性。
另一个解决方案(仍然是“正确的”,但速度很慢)是将安全检查委托给一个小 exe,将其更改为 app.config,运行它,然后将结果作为输出返回(您的提供商可以这样做)。DPAPI 可以为密码传递提供安全性。