gpt4 book ai didi

asp.net-mvc-3 - Multi-Tenancy SQLMembershipProvider ASP.NET MVC

转载 作者:行者123 更新时间:2023-12-03 18:25:16 25 4
gpt4 key购买 nike

我正在尝试使用 Multi-Tenancy ASP.NET MVC 应用程序迁移到 Azure(包括 SQL Azure)。每个客户都有自己的独立数据库,包括他们所有的成员(member)凭证。

我们能够在初始化 SqlMembershipProvider 对象时将连接字符串设置为 SqlMembershipProvider。但是,对不同子域(在同一 session 中)的后续请求不会更改连接字符串。我发现了一个示例,其中实现覆盖了 SqlMembershipProviders ConnectionString,但这在 System.Web dll 版本 4.0 中是不可能的。

我们可以实现一个成员(member)数据库并对其进行身份验证......但我们希望在此 SAAS 模型中保持客户凭据的隔离。

所以问题是如何为每个请求动态更改 SQLMembershipProviders 连接字符串?

Web.config

<membership defaultProvider="TenantMembershipProvider">
<providers>
<clear/>
<add name="TenantMembershipProvider" type="ABC.Infrastructure.MultiTenancy.TenantMembershipProvider, ABC"
connectionStringName="ApplicationServices" enablePasswordRetrieval="true" enablePasswordReset="true" requiresQuestionAndAnswer="false"
requiresUniqueEmail="false" passwordFormat="Clear" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6"
minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" applicationName="/"/>

</providers>
</membership>

处理初始化的TenantMembershipProvider.cs

public class TenantMembershipProvider : SqlMembershipProvider
{

private SiteLinqSession _session;
private MasterSession _masterSession;
private static readonly Dictionary<string, Customer> _customers = new Dictionary<string, Customer>();
private static string _host;


public override void Initialize(string name, NameValueCollection config)
{

base.Initialize(name, config);

string connectionString = GetConnectionString();
FieldInfo connectionStringField = GetType().BaseType.GetField("_sqlConnectionString", BindingFlags.Instance | BindingFlags.NonPublic);
connectionStringField.SetValue(this, connectionString);

}

private string GetConnectionString()
{
var headers = HttpContext.Current.Request.Headers["Host"];
string[] host = headers.Split('.');

_host = host[0];

if (_host == "127") _host = "demo";

var customer = GetSite(_host);

return BuildTenantConnectionString(customer.ConnectionSetting);

}


private Customer GetSite(string host)
{
Customer customer;

//check dictionary if customer exists for the subdomain
_customers.TryGetValue(host, out customer);

if (customer != null)
return customer;

//if not get the customer record and add it to the dictionary
_masterSession = new MasterSession();
var customers = _masterSession.All<Customer>();
customer = customers.SingleOrDefault(x => x.SubDomain == _host);

if (customer != null)
_customers.Add(host, customer);

return customer;
}

private string BuildTenantConnectionString(ConnectionSetting setting)
{

return string.Format("Data Source={0};Initial Catalog={1};User Id={2};Password={3};", setting.DataSource, setting.Catalog, setting.Username, setting.Password);

}
}

最佳答案

通过 Adam 发布的链接节省人们一些时间。

在 Application_PreRequestHandlerExecute 事件的 Global.asax 文件中

    protected void Application_PreRequestHandlerExecute()
{
SetProviderConnectionString(GetConnectionString());
}

private void SetProviderConnectionString(string connectionString)
{
// Set private property of Membership, Role and Profile providers. Do not try this at home!!
var connectionStringField = Membership.Provider.GetType().GetField("_sqlConnectionString", BindingFlags.Instance | BindingFlags.NonPublic);
if (connectionStringField != null)
connectionStringField.SetValue(Membership.Provider, connectionString);

var roleField = Roles.Provider.GetType().GetField("_sqlConnectionString", BindingFlags.Instance | BindingFlags.NonPublic);
if (roleField != null)
roleField.SetValue(Roles.Provider, connectionString);

var profileField = ProfileManager.Provider.GetType().GetField("_sqlConnectionString", BindingFlags.Instance | BindingFlags.NonPublic);
if (profileField != null)
profileField.SetValue(ProfileManager.Provider, connectionString);
}

private string GetConnectionString()
{
return string.Format("Data Source={0};", @".\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|demo.mdf;User Instance=true");
}

如果您创建了自定义membershipProvider,那么您将获得BaseType

   var connectionStringField = Membership.Provider.GetType().BaseType.GetField("_sqlConnectionString", BindingFlags.Instance | BindingFlags.NonPublic);

我不确定这是否是最合适的解决方案,但它似乎完成了为membershipProvider启用动态connectionString的工作,而无需滚动您自己的解决方案。不过感觉有点老套。

关于asp.net-mvc-3 - Multi-Tenancy SQLMembershipProvider ASP.NET MVC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8525297/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com