问题描述
作为测试,我使用 Visual Studio 2013 中的最新模板创建了一个全新的 Asp.Net MVC5 应用程序.我在 Global.asax.cs 中添加了以下方法:
As a test, I created a fresh Asp.Net MVC5 app using the latest template in Visual Studio 2013. I added the following method to Global.asax.cs:
protected void Application_PreSendRequestHeaders()
{
Response.AppendCookie(new HttpCookie("TotalNumberOfCookiesInApplication_EndRequestIs", Response.Cookies.Count + string.Empty));
}
当我启动应用程序并使用注册用户的凭据对/Account/Login 执行 POST 时,返回给客户端的 cookie 是:
When I start the app and do a POST to /Account/Login using the credentials of a registered user, the cookies that get returned to the client are:
请注意,我添加的自定义 cookie 显示在调用 Application_PreSendRequestHeaders() 时响应中没有设置 cookie.尽管如此,所有 Auth cookie 都会到达客户端.我的理解是 Application_PreSendRequestHeaders() 是我们可以挂钩"以修改 cookie 的最后一个阶段.之后 Owin 中间件是否能够以某种方式添加 cookie,还是我遗漏了什么?
Note that the custom cookie I've added shows that there are no cookies set in the response by the time Application_PreSendRequestHeaders() is called. Despite this, all the Auth cookies arrive at the client. I was of the understanding that Application_PreSendRequestHeaders() is the last stage we can "hook" into for modifying cookies. Is the Owin middleware able to somehow add cookies after that, or am I missing something?
(如果您有兴趣,我的动机是:我正在尝试将 auth cookie 的域修改为.abc.com",其中abc.com"是 请求 URI 中主机的最后两部分.我想这样做以支持跨多个子域的身份验证.在全局 Owin 配置 (IAppBuilder
) 的上下文中设置 CookieDomain 是不够,因为请求主机在我们的调试/暂存/生产环境之间发生变化,而且我们经常先将生产代码部署到 Azure 暂存以进行测试,然后再进行 VIP 交换).
(In case you're interested, my motivation for all this is: I'm trying to modify the domain of the auth cookies to be ".abc.com", where "abc.com" is the last two parts of the host in the request URI. I want to do this to support authentication across multiple subdomains. Setting the CookieDomain in the context of the global Owin configuration (IAppBuilder
) isn't enough because the request host changes between our debug/staging/production environments, and we often deploy the production code to Azure staging first for testing before doing a VIP swap).
(另请注意,我知道像 这个,但是它没有解释cookies的实际设置位置)
(Note also that I'm aware of posts like this one, however it doesn't explain where the cookies are actually set)
基于更多的搜索,似乎我正在调查错误的管道.Owin 有自己的管道,所以我发现 这篇文章 描述了我们如何才能钩住它.中提琴……有饼干.如果有人能证实这确实是最明智的做法,那就太好了.
Based on a bit more searching, it seems I'm looking into the wrong pipeline. Owin has its own pipeline, so I found this post which describes how we can hook into it. Viola...there were the cookies. Would be great if anybody could confirm that this is indeed the most sensible way to do it.
编辑 2:
最后决定查看 Katana 源代码并发现我需要做的就是设置我的 cookie 域是我的 CookieAuthenticationProvider 中的以下代码
Finally decided to look into the Katana source code and found out that all I needed to do to get my cookie domains set was the following code in my CookieAuthenticationProvider
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 域:
An even cleaner solution for my case was just to use a custom cookie manager, which set the cookie domain based on the current request URI:
/// <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 身份验证选项中设置:
...which is then set in the Cookie Auth Options in the Owin setup:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
...
CookieManager = new ChunkingCookieManagerWithSubdomains(),
...
}
});
希望对遇到同样问题的人有所帮助.
Hope that helps somebody coming across the same kind of question.
推荐答案
根据 Tieson 的要求,这里是我在上面原始帖子中的编辑摘要,作为答案.
As requested by Tieson, here's a summary of my edits in the original post above, as an answer.
建议的解决方案:使用自定义 cookie 管理器.
Suggested solution: Use a custom cookie manager.
/// <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 身份验证选项中设置:
...which can then be set in the Cookie Auth Options in the Owin setup:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
...
CookieManager = new ChunkingCookieManagerWithSubdomains(),
...
}
});
这篇关于在 Application_EndRequest 阶段之后,Owin 如何设置 Asp.Net Identity 身份验证 cookie?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!