【问题标题】:How to set the AntiForgeryToken cookie path如何设置 AntiForgeryToken cookie 路径
【发布时间】:2016-02-14 05:34:33
【问题描述】:

以前的HtmlHelper.AntiForgeryToken 方法允许覆盖string path 已被弃用。

[ObsoleteAttribute("This method is deprecated. Use the AntiForgeryToken() method instead. To specify a custom domain for the generated cookie, use the <httpCookies> configuration element. To specify custom data to be embedded within the token, use the static AntiForgeryConfig.AdditionalDataProvider property.", 
    true)]
public MvcHtmlString AntiForgeryToken(
    string salt,
    string domain,
    string path
)

告诉你使用&lt;httpCookies&gt;。但是httpCookies Element 没有 PATH 设置。

这是弃用此方法的疏忽吗?覆盖此 cookie 路径的最佳方法是什么? (手动?)在虚拟应用程序中运行网站不会将应用程序路径隐式添加到 __RequestVeririfcation cookie。

【问题讨论】:

  • 您找到解决此问题的方法了吗?

标签: asp.net-mvc csrf asp.net-mvc-5.2 antiforgerytoken cookie-path


【解决方案1】:

查看弃用消息:

“此方法已弃用。请改用 AntiForgeryToken() 方法。要为生成的 cookie 指定自定义域,请使用配置元素。要指定要嵌入到令牌中的自定义数据,请使用静态 AntiForgeryConfig.AdditionalDataProvider 属性。”

它告诉我们,只要读回伪造令牌,我们就可以验证其他参数。所以即使我们不能在cookie中设置路径,我们也可以将路径设置为token内部的属性。稍后验证它,例如:

public class AdditionalDataProvider : IAntiForgeryAdditionalDataProvider
{
    public string GetAdditionalData(HttpContextBase context)
    {
        return AdditionalData(context);
    }

    public bool ValidateAdditionalData(HttpContextBase context, string additionalData)
    {
        var currentData = AdditionalData(context);
        return currentData == additionalData;
    }

    private static string AdditionalData(HttpContextBase context)
    {
        var path = context.Request.ApplicationPath;
        return path;
    }
}

当 asp.net 生成令牌时,它将存储该应用程序的当前路径(或您要验证的任何其他唯一值),并且 如果您有另一个应用程序在不同的路径上运行,当令牌被发送到该应用程序时(由于缺少 cookie 路径),它将根据该应用程序的属性验证以前的应用程序属性。如果它是一组不同的属性,它将失败并拒绝请求。

另外,查看AntiforgeryConfig.cs的代码,如果应用程序在虚拟目录中运行,它将默认将该虚拟目录添加到cookie的名称中:

private static string GetAntiForgeryCookieName()
{
    return GetAntiForgeryCookieName(HttpRuntime.AppDomainAppVirtualPath);
}

// If the app path is provided, we're generating a cookie name rather than a field name, and the cookie names should
// be unique so that a development server cookie and an IIS cookie - both running on localhost - don't stomp on
// each other.
internal static string GetAntiForgeryCookieName(string appPath)
{
    if (String.IsNullOrEmpty(appPath) || appPath == "/")
    {
        return AntiForgeryTokenFieldName;
    }
    else
    {
        return AntiForgeryTokenFieldName + "_" + HttpServerUtility.UrlTokenEncode(Encoding.UTF8.GetBytes(appPath));
    }
}

所以它会是这样的: _RequestVerificationToken vs _RequestVerificationToken_L2RIdjAz0

意思是 App2 虽然可以从 App1 接收令牌,但它无法读取它们,因为它总是只寻找 App2 验证令牌。

HTH

【讨论】:

  • 这很好,但它仍然不写入 cookie 上的路径属性。 See
【解决方案2】:

对于 ASP.NET Core - 请参阅:AntiforgeryOptions Class

Cookie - 确定用于创建防伪的设置 饼干。

前(改编自Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core):

services.AddAntiforgery(options => 
{
    options.Cookie.Path = "Path";
});

【讨论】:

    【解决方案3】:

    覆盖 AntiForgeryToken 的 cookie 配置(路径、HttpOnly 等)的最佳方法是封装 (Microsoft team post)。

    可以配置 cookie 路径,而不是在属性上设置。

    public static class AntiForgeryTokenExtensions
    {
        ///<summary>
        ///Generates a hidden form field (anti-forgery token) that is 
        ///validated when the form is submitted. Furthermore, this extension 
        ///applies custom settings on the generated cookie. 
        ///</summary>
        ///<returns>Generated form field (anti-forgery token).</returns>
        public static MvcHtmlString AntiForgeryTokenExtension(this HtmlHelper html)
        {
            // Call base AntiForgeryToken and save its output to return later.
            var output = html.AntiForgeryToken();
            
            // Check that cookie exists
            if(HttpContext.Current.Response.Cookies.AllKeys.Contains(AntiForgeryConfig.CookieName))
            {
                // Set cookie into the variable
                var antiForgeryTokenCookie = HttpContext.Current.Response.Cookies.Get(AntiForgeryConfig.CookieName);
                
                // Set cookie configuration
                antiForgeryTokenCookie.Path = "/Path";
                // antiForgeryTokenCookie.HttpOnly = true;
                // ...
            }
            
            return output;
        }
    }
    

    最后一个必须做的改变是 replace AntiForgeryToken() for AntiForgeryTokenExtension() 如果它是现有项目。

    注意事项

    • 使用此代码,您可以将 AntiForgeryToken cookie 配置为普通 cookie。
    • 也可以向此方法添加输入参数,但我不确定这是否是一个好习惯。
    • 获取 cookie 的方法有很多种,但我认为通过 Response.Cookies 是“最正确的”,因为它是一个响应 cookie。

    重要

    在获取cookie之前需要先检查cookie是否存在。如果您尝试获取一个不存在的响应 cookie,它将被生成。请求 cookie 不会发生这种情况。

    饼干知识

    这不是问题本身,而是解释了部分代码,知道我们何时使用 cookie 非常重要,所以我认为在这里也有这些信息是件好事。

    • 所有Response.Cookies都在Request.Cookies中,但不是全部 Request.Cookies 在 Response.Cookies 中。

    • 如果您创建 Response.Cookie,它也会出现在 Request.Cookies 中。

    • 如果您创建 Request.Cookie,它将不会出现在 Response.Cookies 中。

    • 如果您尝试从 Request.Cookies 获取不存在的 cookie,它将返回 null。

    • 如果您尝试获取一个不存在的 cookie Response.Cookies,它将返回一个新生成的 cookiee。

    来源

    有开发人员告诉使用封装和许多其他可能有用的东西的链接。 Microsoft developers recommendations and information

    cookies、Request.Cookies 和 Response.Cookies 区别的知识来源。

    Difference between request cookies and response cookies

    Difference between request cookies and response cookies 2

    Check if cookie exist and difference between kind of cookies

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-15
      • 2012-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-31
      • 2023-04-01
      相关资源
      最近更新 更多