【发布时间】:2018-01-05 11:15:19
【问题描述】:
我有一个单页应用程序(用户加载一堆 HTML/JS,然后发出 AJAX 请求而无需再次调用 MVC - 仅通过 WebAPI)。在 WebAPI 中,我有以下内容:
public sealed class WebApiValidateAntiForgeryTokenAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(
System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (actionContext == null)
{
throw new ArgumentNullException(nameof(actionContext));
}
if (actionContext.Request.Method.Method == "POST")
{
string requestUri = actionContext.Request.RequestUri.AbsoluteUri.ToLower();
if (uriExclusions.All(s => !requestUri.Contains(s, StringComparison.OrdinalIgnoreCase))) // place some exclusions here if needed
{
HttpRequestHeaders headers = actionContext.Request.Headers;
CookieState tokenCookie = headers
.GetCookies()
.Select(c => c[AntiForgeryConfig.CookieName]) // __RequestVerificationToken
.FirstOrDefault();
string tokenHeader = string.Empty;
if (headers.Contains("X-XSRF-Token"))
{
tokenHeader = headers.GetValues("X-XSRF-Token").FirstOrDefault();
}
AntiForgery.Validate(!string.IsNullOrEmpty(tokenCookie?.Value) ? tokenCookie.Value : null, tokenHeader);
}
}
base.OnActionExecuting(actionContext); // this is where it throws
}
}
在 Global.asax 注册:
private static void RegisterWebApiFilters(HttpFilterCollection filters)
{
filters.Add(new WebApiValidateAntiForgeryTokenAttribute());
filters.Add(new AddCustomHeaderFilter());
}
有时,我会在日志中看到 The anti-forgery cookie token and form field token do not match 错误。发生这种情况时,tokenCookie.value 和 tokenHeader 都不为空。
客户端,我所有的 AJAX 请求都使用以下内容:
beforeSend: function (request) {
request.setRequestHeader("X-XSRF-Token", $('input[name="__RequestVerificationToken"]').attr("value"););
},
使用 Razor 在我的 SPA 页面上生成一次令牌:
@Html.AntiForgeryToken()
我在 Web.config 中设置了我的机器密钥。
这可能是什么原因造成的?
更新 我刚刚检查了日志,有时我也会看到:
提供的防伪令牌用于用户“”,但当前用户是“someuser@domain.com”。几秒钟前
当用户在登录时刷新他们的 SPA 实例时会发生这种情况。然后 SPA 出于某种原因将它们放入登录页面而不是内部页面(User.Identity.IsAuthenticated 为真) - 然后他们无法登录因为这个错误。清爽将它们拉回室内。不知道这意味着什么,但我认为更多信息不会有什么坏处。
【问题讨论】:
-
防伪令牌在 cookie 上使用超时,所以这可能是原因。
-
@TasosK。我一直在监视它,它似乎与超时无关 - 几天后我成功验证了令牌,并在几秒钟或几分钟后看到失败。
-
@SB2055 你试过在登录方法上禁用缓存吗?
-
不确定这是否会有很大帮助,但您能否说明您使用的是最新的网络 API,即
Web API 2.2 - 5.2.3? -
@SB2055 这有点牵强,但请尝试在您使用的登录方法上添加一个 {[OutputCache(NoStore=true, Duration = 0, VaryByParam= "None")]} 属性。
标签: asp.net asp.net-mvc asp.net-web-api csrf antiforgerytoken