具有 ASP.NET 标识的可变 cookie 路径

Variable cookie path with ASP.NET Identity

我们将多租户 MVC 应用程序从 ASP.NET 成员身份提供程序迁移到 ASP.NET 身份。

这是我的Startup.Auth.cs(简体):

public partial class Startup
{
    public void ConfigureAuth(IAppBuilder app)
    {
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            Provider = new CookieAuthenticationProvider
            {
                OnValidateIdentity =
                    SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, Identity, int>(
                        TimeSpan.FromMinutes(30),
                        (manager, user) =>
                            manager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie),
                        clIdentity => clIdentity.GetUserId<int>())
            }
        });
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
}

在我们的多租户应用程序中,每个租户都有自己的 'slug'(例如 http://example.com/tenant1/ and http://example.com/tenant2/

但是,目前,cookie 存储在根目录中。这会导致安全问题,因为来自租户 1 的用户会自动从租户 2 登录网站。

我们如何使 CookiePath(在 CookieAuthenticationOptions 中)变量使其根据租户而变化?

我在 dampee 的帮助下解决了这个问题。

CookieAuthenticationOptions 对象中的 CookiePath 仅计算一次:在应用程序启动时。 最简单的解决方案(解决方法)是创建一个派生的 CookieAuthenticationProvider,它覆盖 ResponseSignInResponseSignOut。 他们都有一个名为 context 的参数,其中有一个名为 CookiePath 的 属性。在这两个方法中修改此 属性 以更改 CookiePath。 您也可以 use the class I created.

然后您所要做的就是将 CookieAuthenticationOptions 中的 CookieAuthenticationProvider 替换为您刚刚创建的

这适用于 ApplicationCookie。 ExternalSignInCookie 无关紧要,因为它仅在使用外部登录名登录时临时使用。

改进 SamuelDebruyn 自己的解决方案,我发现您可以使用 AuthenticationProperties 对象将登录调用的路径传递给提供者。这样,您就可以从源代码中显式传递它,而不是像他的要点所示那样从请求上下文中提取路径:

// method inside web api controller
private void SignIn(string name, string cookiePath)
{
    var claims = new[] { new Claim(ClaimTypes.Name, name) };
    var identity = new ClaimsIdentity(claims, "ApplicationCookie");

    var options = new AuthenticationProperties();
    options.Dictionary["CustomCookiePath"] = cookiePath;

    var authManager = Request.GetOwinContext().Authentication;
    authManager.SignIn(options, identity);
}

// Startup.cs
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    Provider = new CustomCookieProvider()
});

// custom provider
public class CustomCookieProvider : CookieAuthenticationProvider
{
    public override void ResponseSignIn(CookieResponseSignInContext context)
    {
        context.CookieOptions.Path = context.Properties.Dictionary["CustomCookiePath"];
        base.ResponseSignIn(context);
    }
}

您可以使用自定义 ICookieManager 根据请求中的内容动态 return 将 cookie 值 CookieAuthenticationProvider ,为此您仍然需要将 CookiePath 保持为“/”,然后将其保留到 ICookieManager 到 return(或写入)您想要的 cookie。 CookieManagerCookieAuthenticationOptions 上的一个选项。我在这里写了博客:http://shazwazza.com/post/owin-cookie-authentication-with-variable-cookie-paths/