自定义OWIN CookieAuthenticationProvider在第一次/冷启动时失败

时间:2014-05-08 18:30:59

标签: c# asp.net authentication cookies owin

我们有一个自定义Cookie身份验证提供程序,它将auth cookie设置为包含.domain.com而不是domain.commy.domain.com等主机名。我们这样做,因此cookie可用于所有子域和域。它很简单,如下所示。

问题

在应用程序冷启动后的第一次尝试中,cookie STILL承载域my.domain.com(我们的登录在my.domain.com上)DESPITE在执行{{1}后将其设置为.domain.com下面的代码(使用断点检查)。在后续登录尝试中,cookie主机名没问题。

问题

我如何解决这个问题,以便即使在第一次尝试时也能正常工作?

代码

自定义Cookie身份验证

SubdomainCookieAuthentication

这是在Owin启动类中初始化的,如下所示

课程:public class SubdomainCookieAuthentication : CookieAuthenticationProvider { public override void ResponseSignIn(CookieResponseSignInContext context) { // We need to add a "." in front of the domain name to // allow the cookie to be used on all sub-domains too var hostname = context.Request.Uri.Host; // works for www.google.com => google.com // will FAIL for www.google.co.uk (gives co.uk) but doesn't apply to us var dotTrimmedHostname = Regex.Replace(hostname, @"^.*(\.\S+\.\S+)", "$1"); context.Options.CookieDomain = dotTrimmedHostname; base.ResponseSignIn(context); } }

档案:Startup

App_start\Startup.Auth.cs

1 个答案:

答案 0 :(得分:3)

我在使用ResponseSignIn方法第一次尝试时没有设置Cookie域时遇到同样的问题。我能够通过将Owin库更新为3.x并使用新的CookieManager来设置域来解决此问题。从这篇文章中找到了这个解决方案:

How is Owin able to set the Asp.Net Identity authentication cookies after the Application_EndRequest stage?

public class ChunkingCookieManagerWithSubdomains : ICookieManager
{
    private readonly ChunkingCookieManager _chunkingCookieManager;

    public ChunkingCookieManagerWithSubdomains()
    {
        _chunkingCookieManager = new ChunkingCookieManager();
    }

    public string GetRequestCookie(IOwinContext context, string key)
    {
        return _chunkingCookieManager.GetRequestCookie(context, key);
    }

    public void AppendResponseCookie(IOwinContext context, string key, string value, CookieOptions options)
    {
        options.Domain = context.Request.Uri.GetHostWithoutSubDomain();
        _chunkingCookieManager.AppendResponseCookie(context, key, value, options);
    }

    public void DeleteCookie(IOwinContext context, string key, CookieOptions options)
    {
        options.Domain = context.Request.Uri.GetHostWithoutSubDomain();
        _chunkingCookieManager.DeleteCookie(context, key, options);
    }
}

public static class UriExtensions
{
    public static string GetHostWithoutSubDomain(this Uri url)
    {
        if (url.HostNameType == UriHostNameType.Dns)
        {
            string host = url.Host;
            if (host.Split('.').Length > 2)
            {
                int lastIndex = host.LastIndexOf(".");
                int index = host.LastIndexOf(".", lastIndex - 1);
                return host.Substring(index + 1);
            }
            else
            {
                return host;
            }
        }

        return null;
    }
}

然后,在Startup.Auth.cs中注册它

app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        ...
        CookieManager = new ChunkingCookieManagerWithSubdomains(), 
        ...
    }
);