在我的ASP.NET MVC应用程序中,我实现了自定义AntiForgeryToken属性,该属性验证AntiForgeryToken的每个POST请求。这样我就不必在每个操作方法上添加[ValidateAntiForgeryToken]
属性,而是为所有POST请求全局处理。
最近,我为我的网络应用程序启用了内容安全策略。 CSP如下所示
default-src 'none' https:;
script-src 'self';
style-src 'self';
img-src 'self' data:;
font-src 'self';
report-uri /csp/report;
浏览器将违规报告发布到/csp/report
网址,但没有防伪令牌,因此我的全局防伪验证失败。
在_layout.cshtml
页面中,我创建了令牌@Html.AntiForgeryToken()
。因此,为每个视图创建了令牌。
当浏览器POST csp-report时,无论如何都告诉浏览器如果在DOM中可用,还会发布防伪标记?
现在只是为了让它正常工作,我更新了我的防伪验证逻辑,以跳过/csp/report/
网址的验证。
更新1
public class ValidatePostAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
{
private const string _tokenKey = "__RequestVerificationToken";
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (filterContext.HttpContext.Request.HttpMethod.ToUpper() == "POST")
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
if (filterContext.HttpContext.Request.Cookies.Get(AntiForgeryConfig.CookieName) == null)
{
throw new HttpPostAntiForgeryException("Invalid Verification Cookie.");
}
if (filterContext.HttpContext.Request.Headers.Get(_tokenKey) == null)
{
throw new HttpPostAntiForgeryException("Invalid Verification Token.");
}
AntiForgery.Validate(filterContext.HttpContext.Request.Cookies[AntiForgeryConfig.CookieName].Value, filterContext.HttpContext.Request.Headers[_tokenKey]);
}
else
{
// dont validate post for content security policy report
if (filterContext.HttpContext.Request.Url.AbsolutePath.ToLower().Contains("csp/report"))
{
return;
}
// validate non ajax POST
AntiForgery.Validate();
}
}
}
}