如何设置 AntiForgeryToken cookie 路径
How to set the AntiForgeryToken cookie path
以前的 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
)
告诉你使用<httpCookies>
。但是 httpCookies Element 没有 PATH 的设置。
这是对弃用此方法的疏忽吗?覆盖此 cookie 路径的最佳方法是什么? (手动?)运行 虚拟应用程序中的网站未隐式将应用程序路径添加到 __RequestVeririfcation cookie。
查看弃用消息:
"This method is deprecated. Use the AntiForgeryToken() method instead. To specify a custom domain for the generated cookie, use the configuration element. To specify custom data to be embedded within the token, use the static AntiForgeryConfig.AdditionalDataProvider property."
它告诉我们只要读回伪造令牌,我们就可以验证其他参数。所以即使我们不能在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 对比
_RequestVerificationToken_L2RIdjAz0
意思是 App2 虽然可以从 App1 接收令牌,但它无法读取它们,因为它将始终只查找 App2 验证令牌。
HTH
对于 ASP.NET 核心 - 请参阅:AntiforgeryOptions Class
Cookie - Determines the settings used to create the antiforgery
cookies.
Ex(改编自Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core):
services.AddAntiforgery(options =>
{
options.Cookie.Path = "Path";
});
覆盖 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() 对于 AntiForgeryTokenExtension() 如果它是 现有项目。
注释
- 使用此代码,您可以将 AntiForgeryToken cookie 配置为普通 cookie。
- 也可以向此方法添加输入参数,但我不确定这是否是一个好的做法。
- 有多种获取 cookie 的方法,但我认为通过 Response.Cookies 是 “最正确的”,因为它是响应 cookie。
重要
获取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,它将 return一个空值.
如果你试图获取一个不存在的cookieResponse.Cookies它会return一个新生成的cookieie.
来源
开发人员告诉 link 使用封装和许多其他可能有用的东西。
Microsoft developers recommendations and information
Cookie 知识来源,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
以前的 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
)
告诉你使用<httpCookies>
。但是 httpCookies Element 没有 PATH 的设置。
这是对弃用此方法的疏忽吗?覆盖此 cookie 路径的最佳方法是什么? (手动?)运行 虚拟应用程序中的网站未隐式将应用程序路径添加到 __RequestVeririfcation cookie。
查看弃用消息:
"This method is deprecated. Use the AntiForgeryToken() method instead. To specify a custom domain for the generated cookie, use the configuration element. To specify custom data to be embedded within the token, use the static AntiForgeryConfig.AdditionalDataProvider property."
它告诉我们只要读回伪造令牌,我们就可以验证其他参数。所以即使我们不能在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 对比 _RequestVerificationToken_L2RIdjAz0
意思是 App2 虽然可以从 App1 接收令牌,但它无法读取它们,因为它将始终只查找 App2 验证令牌。
HTH
对于 ASP.NET 核心 - 请参阅:AntiforgeryOptions Class
Cookie - Determines the settings used to create the antiforgery cookies.
Ex(改编自Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core):
services.AddAntiforgery(options =>
{
options.Cookie.Path = "Path";
});
覆盖 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() 对于 AntiForgeryTokenExtension() 如果它是 现有项目。
注释
- 使用此代码,您可以将 AntiForgeryToken cookie 配置为普通 cookie。
- 也可以向此方法添加输入参数,但我不确定这是否是一个好的做法。
- 有多种获取 cookie 的方法,但我认为通过 Response.Cookies 是 “最正确的”,因为它是响应 cookie。
重要
获取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,它将 return一个空值.
如果你试图获取一个不存在的cookieResponse.Cookies它会return一个新生成的cookieie.
来源
开发人员告诉 link 使用封装和许多其他可能有用的东西。 Microsoft developers recommendations and information
Cookie 知识来源,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