2017-08-03 57 views
0

我使用標準的ASP.Net身份Cookie身份驗證爲我的ASP.NET MVC項目設置了多租戶。因此,我擁有可在mysite.com上訪問的主租戶(常規租戶以及一些租戶管理工具的訪問權限),以及t1.mysite.com,t2.mysite.com上的不同租戶。ASP.NET身份Multitenant登錄問題

t2.mysite.com上的登錄名在t2.mysite.com上無效,這正是我想要的。但是,如果我登錄到mysite.com,然後登錄,訪問tX.mysite.com,看起來好像我仍然登錄。即使應用程序的身份我甚至不存在。

是否有任何方法可以確保爲mysite.com收到的身份驗證Cookie在tX.mysite.com上無效,以便管理員不會意外地終止於非工作租戶(GUI可見,但您不能做任何事情,因爲對於mysite.com登錄不上tx.mysite.com有效的,所以最好只顯示登錄屏幕)

回答

0

在你App_Start\Startup.Auth.cs文件,你應該有一些關於OnValidateIdentity

app.UseCookieAuthentication(new CookieAuthenticationOptions 
{ 
    Provider = new CookieAuthenticationProvider 
    { 
     OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<Infrastructure.Identity.UserManager, ApplicationUser>(
      validateInterval: TimeSpan.FromMinutes(30), 
      regenerateIdentity: (manager, user) => manager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie)) 
    }, 
    // Other stuff 
});   

看到參數validateInterval - 默認情況下它被設置爲30分鐘。這是Cookie實際上與數據庫中的值進行比較的頻率。

將值更改爲TimeSpan.FromSeconds(30)。這將每30秒將cookie與數據庫中的值進行比較,如果租戶的身份無效 - 則會向用戶顯示登錄入口。

您也可以將其更改爲0,但我認爲這會超載您的數據庫 - 每次請求都會有一些調用數據庫。

也有一個屬性CookieDomain財產上CookieauthenticationOptions

app.UseCookieAuthentication(new CookieAuthenticationOptions 
{ 
    // other stuff 
    CookieDomain = "example.com" 
}); 

這可以幫助你,而是因爲這個項目在流水線這麼早配置可能很難在運行時重新配置。

另一種選擇是有多個cookie authenticaion中間件,但如果你的租戶數量是已知的,非常有限的,這隻會工作:

app.UseCookieAuthentication(new CookieAuthenticationOptions 
{ 
    // other stuff 
    AuthenticationType = "myTenant1", 
    CookieDomain = "t1.example.com" 
}); 

app.UseCookieAuthentication(new CookieAuthenticationOptions 
{ 
    // other stuff 
    AuthenticationType = "myTenant2", 
    CookieDomain = "t2.example.com" 
}); 

但這可能會給你比它更頭疼的實際價值。

+0

嗯,我想這將在30秒後將用戶重定向到正確的登錄頁面,這比沒有好,但仍然不是我期待的即時性。由於我的數據存儲是「遠程」,因此我想保留請求的數量。 因此,是不是有一種方法來查看授權cookie,比較域,如果它只是部分匹配,則返回未授權。我目前正在涉足一個自定義的CookieAuthenticationProvider,但我還沒有到那裏 - 我懷疑這可能會遇到同樣的侷限。 – user3566056

+0

@ user3566056更新了我的答案 – trailmax

0

所以我找到了另一種方法來處理這個問題。看起來我可以直接掛鉤cookie身份驗證,並且如果來自錯誤的租戶,則只是拒絕身份。

所以我寫了我的自定義CookieAuthenticationProvider

public class TenantCookieAuthenticationProvider: CookieAuthenticationProvider 
{ 

    public override Task ValidateIdentity(CookieValidateIdentityContext context) 
    { 
     string tenantId = SubdomainRoute.GetSubdomain(context.Request.Host.Value); 
     if (!string.IsNullOrEmpty(tenantId)) // we're trying to access mysite.com from x.mysite.com 
     { 
      context.RejectIdentity(); 
      return Task.FromResult<int>(0); 
     } 
     return base.ValidateIdentity(context); 
    } 
} 

,並掛接到認證管道在Startup.cs

app.UseCookieAuthentication(new CookieAuthenticationOptions 
     { 
      AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, 
      LoginPath = new PathString("/Account/Login"), 
      Provider = new TenantCookieAuthenticationProvider 
      { 
       // Enables the application to validate the security stamp when the user logs in. 
       // This is a security feature which is used when you change a password or add an external login to your account. 
       OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
        validateInterval: TimeSpan.FromMinutes(30), 
        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)) 
      } 
     }); 

當然,這只是成功的一半..另一半是不是如果它是有效的租戶用戶,則拒絕該身份。由於我在創建用戶時將tenantId添加爲聲明,因此我可以提取並比較這些聲明,以免拒絕有效的租戶用戶。所以我適應ValidateIdentity如下

public override Task ValidateIdentity(CookieValidateIdentityContext context) 
    { 
     System.Security.Claims.Claim tenantClaim = context.Identity.Claims.FirstOrDefault(x => x.Subject.Name == "tenant"); 
     string tenantId = SubdomainRoute.GetSubdomain(context.Request.Host.Value); 
     if (tenantClaim != null) 
     { 
      if (tenantId != tenantClaim.Value) 
      { 
       context.RejectIdentity(); 
       return Task.FromResult<int>(0); 
      } 
     } 
     else 
     { 
      if (!string.IsNullOrEmpty(tenantId)) // we're trying to access audm.local from x.audm.local 
      { 
       context.RejectIdentity(); 
        return Task.FromResult<int>(0); 
      } 
     } 
     return base.ValidateIdentity(context); 
    } 

現在我甚至有一個額外的安全層,使用戶無法「租戶之間跳」。