asp.net-mvc - Owin 如何在 Application_EndRequest 阶段之后设置 Asp.Net 身份验证 cookie?

标签 asp.net-mvc cookies asp.net-mvc-5 asp.net-identity owin

作为测试,我使用 Visual Studio 2013 中的最新模板创建了一个新的 Asp.Net MVC5 应用程序。我将以下方法添加到 Global.asax.cs:

    protected void Application_PreSendRequestHeaders()
    {
        Response.AppendCookie(new HttpCookie("TotalNumberOfCookiesInApplication_EndRequestIs", Response.Cookies.Count + string.Empty));
    }

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

enter image description here

请注意,我添加的自定义 cookie 显示,在调用 Application_PreSendRequestHeaders() 时,响应中没有设置任何 cookie。尽管如此,所有 Auth cookie 都会到达客户端。我认为 Application_PreSendRequestHeaders() 是我们可以“ Hook ”修改 cookie 的最后一个阶段。 Owin 中间件是否能够以某种方式添加 cookie 之后,或者我错过了什么?

(如果您感兴趣,我做这一切的动机是:我正在尝试将身份验证 cookie 的域修改为“.abc.com”,其中“abc.com”是 请求 URI 中主机的最后两个部分。我想这样做是为了支持跨多个子域的身份验证。在全局 Owin 配置 (IAppBuilder) 的上下文中设置 CookieDomain 不是“这还不够,因为请求主机在我们的调试/暂存/生产环境之间发生变化,并且我们通常会先将生产代码部署到 Azure 暂存进行测试,然后再进行 VIP 交换。

(另请注意,我知道类似 this one 的帖子,但它没有解释 cookie 的实际设置位置)

编辑:

根据更多的搜索,我似乎正在寻找错误的管道。 Owin有自己的管道,所以我找到了this post它描述了我们如何连接它。维奥拉……还有 cookies 。如果有人能够确认这确实是最明智的方法,那就太好了。

编辑2:

最后决定查看 Katana 源代码,发现我需要做的就是设置 Cookie 域,只需在 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 域:

/// <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 身份验证选项中进行设置:

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

希望对遇到同样问题的人有所帮助。

最佳答案

根据 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 身份验证选项中进行设置:

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

关于asp.net-mvc - Owin 如何在 Application_EndRequest 阶段之后设置 Asp.Net 身份验证 cookie?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28252478/

相关文章:

c# - 模型更改后更新数据库 - Entity Framework 7

javascript - 无法显示cookie

security - ColdFusion:CFID 和 CFToken 在每次页面请求时发生变化

javascript - __doPostBack() 导致回发但不调用 aspx 页面中的按钮单击事件

javascript - 将 JavaScript 日期时间区域传递给 MVC Controller ,无需 ActionResult View

c# - 第二次保存到上下文时继续获取 "A second operation started on this context before a previous operation completed"。

python-3.x - FastAPI:注销后删除 cookie 不起作用

c# - ASP.NET MVC 5 改变 View 模板

c# - C#中如何将字符串中每个单词的首字母大写

c# - 使用 Salesforce 的 MVC OAuth 身份验证返回登录页面