Owin如何在Application_EndRequest阶段后设置Asp.Net Identity身份验证cookie?

7
作为一项测试,我使用Visual Studio 2013中最新的模板创建了一个全新的Asp.Net MVC5应用程序。我在Global.asax.cs中添加了以下方法:
    protected void Application_PreSendRequestHeaders()
    {
        Response.AppendCookie(new HttpCookie("TotalNumberOfCookiesInApplication_EndRequestIs", Response.Cookies.Count + string.Empty));
    }

当我启动应用程序并使用已注册用户的凭据进行POST到/Account/Login时,返回给客户端的cookie为:

enter image description here

请注意,我添加的自定义cookie显示在调用Application_PreSendRequestHeaders()时响应中没有任何cookie被设置。尽管如此,所有的Auth cookie都到达了客户端。我理解Application_PreSendRequestHeaders()是我们可以“挂接”以修改cookie的最后阶段。Owin中间件能否在此之后以某种方式添加cookie,或者我漏掉了什么?
(如果您感兴趣,我的动机是:我正在尝试修改auth cookies的域为“.abc.com”,其中“abc.com”是请求URI中主机的最后两部分。我希望这样做可以支持多个子域的身份验证。在全局Owin配置(IAppBuilder)上下文中设置CookieDomain并不足够,因为我们的调试/暂存/生产环境之间请求主机会发生变化,我们经常先将生产代码部署到Azure暂存进行测试,然后再进行VIP交换。)
(还要注意,我知道像这篇文章这样的文章,但它并没有解释cookie实际上是在哪里设置的)
编辑:
基于更多的搜索,似乎我正在研究错误的管道。Owin有自己的管道,所以我找到了this post,它描述了我们如何钩入它。嘿...那里就有了cookie。如果有人能确认这确实是最明智的方法,那就太好了。
编辑2:
最终决定查看Katana源代码,并发现我需要做的就是在我的CookieAuthenticationProvider中添加以下代码来设置我的cookie域。
                OnResponseSignIn = context =>
                {
                    // Example only!
                    context.CookieOptions.Domain = context.Request.Uri.Host;
                },
                OnResponseSignOut = context =>
                {
                    // Example only!
                    context.CookieOptions.Domain = context.Request.Uri.Host;
                }

编辑3:

对于我的情况,更加简洁的解决方案是使用自定义cookie管理器,该管理器根据当前请求URI设置cookie域:

/// <summary>
/// This class simply appends the cookie domain to the usual auth cookies
/// </summary>
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)
    {
        // Simplification (use the context parameter to get the required request info)
        options.Domain = ".domainBasedOnRequestInContext.com";
        _chunkingCookieManager.AppendResponseCookie(context, key, value, options);
    }

    public void DeleteCookie(IOwinContext context, string key, CookieOptions options)
    {
        // Simplification (use the context parameter to get the required request info)
        options.Domain = ".domainBasedOnRequestInContext.com";
        _chunkingCookieManager.DeleteCookie(context, key, options);
    }
}

然后将其设置在 Owin 设置中的 Cookie Auth 选项中:

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

希望这能帮助到遇到相同问题的人。

实际上,在头部发送之前,还有一个阶段可以挂钩。HttpApplication.PreSendRequestHeaders。 - Erik Funkenbusch
谢谢Erik...在修改此情况下的Owin auth cookies任务中,这并没有帮助,但你是正确的,我的陈述是不正确的。我会更新给其他遇到类似问题的人。 - sammy34
看起来这些编辑作为自我回答应该可以很好地工作;如果您将它们移动到答案中,我会点赞。 - Tieson T.
1个回答

7
根据Tieson的要求,以下是我对上面原帖中编辑的摘要。

建议解决方法:使用自定义cookie管理器。

/// <summary>
/// This class simply appends the cookie domain to the usual auth cookies
/// </summary>
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)
    {
        // Simplification (use the context parameter to get the required request info)
        options.Domain = ".domainBasedOnRequestInContext.com";
        _chunkingCookieManager.AppendResponseCookie(context, key, value, options);
    }

    public void DeleteCookie(IOwinContext context, string key, CookieOptions options)
    {
        // Simplification (use the context parameter to get the required request info)
        options.Domain = ".domainBasedOnRequestInContext.com";
        _chunkingCookieManager.DeleteCookie(context, key, options);
    }
}

然后可以将其设置在 Owin 设置的 Cookie Auth 选项中:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接