【问题标题】:How is Owin able to set the Asp.Net Identity authentication cookies after the Application_EndRequest stage?Owin 如何在 Application_EndRequest 阶段之后设置 Asp.Net Identity 身份验证 cookie?
【发布时间】:2015-03-30 21:47:26
【问题描述】:

作为测试,我使用 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 是:

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

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

(另请注意,我知道像 this one 这样的帖子,但它没有说明 cookie 的实际设置位置)

编辑:

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

编辑 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(), 
            ...
            }
        });

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

【问题讨论】:

  • 实际上,还有一个阶段,您可以在发送标头之前进行挂钩。 HttpApplication.PreSendRequestHeaders.
  • 感谢 Erik ...在这种情况下,它对修改 Owin 身份验证 cookie 的任务没有帮助,但您是正确的,因为我的陈述不正确。我会为遇到它的其他人更新。
  • 似乎这些编辑可以很好地作为自我回答;如果您将他们移至答案,我会投票。

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


【解决方案1】:

应 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(), 
            ...
            }
        });

【讨论】:

    猜你喜欢
    • 2018-05-10
    • 2015-10-09
    • 2023-04-05
    • 1970-01-01
    • 2017-06-27
    • 2016-03-28
    • 2017-05-06
    • 1970-01-01
    • 2018-12-30
    相关资源
    最近更新 更多