asp.net-mvc-3 – 多租户SQLMembershipProvider ASP.NET MVC
我正在尝试使用多租户ASP.NET MVC应用程序迁移到Azure(包括SQL Azure).每个客户都拥有自己的数据库,这些数据库是独立的,包括所有会员资格.
我们可以在初始化SqlMembershipProvider对象时将连接字符串设置为SqlMembershipProvider.但是,对不同子域(在同一会话中)的后续请求不会更改连接字符串.我找到了一个示例,其中实现重写了SqlMembershipProviders ConnectionString,但这在System.Web dll的4.0版本中是不可能的. 我们可以实现单个成员资格数据库并对其进行身份验证……但我们希望在此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而无需自行滚动.虽然觉得有点hackish. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net – CollapsiblePanelExtender在初始页面加载时不会
- asp.net – log4net没有记录ThreadContext
- asp.net core系列 49 Identity 授权(上)
- asp.net-mvc – 如何在不使用ASP.Net MVC html助手的情况下
- asp.net-mvc-3 – 在控制器操作完成后使用Javascript隐藏图
- ASP.NET Web窗体是否阻止双击提交?
- asp.net 中用easyui中的treegird的简单使用
- asp.net-mvc-4 – DataAnnotation Range属性的客户端验证之
- asp.net-mvc – 如何检查是否为浏览器启用了cookie
- Response.Flush不工作ASP.NET
- asp.net – .NET Core WebAPI OpenIdDict(凭据流
- asp.net-mvc – DisplayFor和ValueFor之间的区别
- 从ASP.NET Core Web API将多GB文件流式传输到AWS
- 初识ABP vNext(10):ABP设置管理
- 文件无刷新上传(swfUpload与uploadify)
- 在Entity Framework中使用存储过程(四):如何为
- asp.net – 动态编译的文件在.NET中使用csc.exe吗
- asp.net – 在SQL SERVER 2005上启用CLR是否存在
- asp.net – 防止页面在回发后滚动
- asp.net-mvc – 提交表单并将数据传递给FileStre