SB2*_*055 9 asp.net asp.net-mvc csrf antiforgerytoken asp.net-web-api
我有一个单页面的应用程序(用户加载一堆HTML/JS,然后在没有另一次调用MVC的情况下发出AJAX请求 - 仅通过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
}
}
Run Code Online (Sandbox Code Playgroud)
在Global.asax注册:
private static void RegisterWebApiFilters(HttpFilterCollection filters)
{
filters.Add(new WebApiValidateAntiForgeryTokenAttribute());
filters.Add(new AddCustomHeaderFilter());
}
Run Code Online (Sandbox Code Playgroud)
偶尔,我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"););
},
Run Code Online (Sandbox Code Playgroud)
使用Razor在SPA页面上生成令牌一次:
@Html.AntiForgeryToken()
Run Code Online (Sandbox Code Playgroud)
我在Web.config中设置了我的机器密钥.
可能是什么导致了这个?
更新 我只是检查了日志,我有时也会看到这个:
提供的防伪令牌适用于用户"",但当前用户为"someuser@domain.com".几秒钟前
当用户在登录时刷新其SPA实例时会发生这种情况.由于某种原因,SPA会将它们放入登录页面而不是内页(User.Identity.IsAuthenticated
是真的) - 然后由于此错误他们无法登录.清爽将它们拉回来.不知道这意味着什么,但我认为更多的信息不会伤害.
我的回答建议不要尝试在 AJAX 调用中使用基于令牌的 CSRF 保护,而是依赖 Web 浏览器的本机 CORS 功能。
\n\n基本上,从浏览器到后端服务器的任何 AJAX 调用都会检查域来源(也称为加载脚本的域)。如果域匹配(JS 托管域 == 目标 AJAX 服务器域),则 AJAX 调用执行正常,否则返回null
.
如果攻击者尝试在自己的服务器上托管恶意 AJAX 查询,并且您的后端服务器没有 CORS 策略允许他这样做(默认情况下是这种情况),那么攻击将会失败。
\n\n因此,本质上,CSRF 保护在 AJAX 调用中毫无用处,您可以通过不尝试处理该问题来降低技术债务。
\n\n更多信息:- Mozilla 基金会
\n\n代码示例 - 使用您的控制台检查器!
\n\n<html>\r\n<script>\r\nfunction reqListener () {\r\n console.log(this.responseText);\r\n}\r\n\r\nvar oReq = new XMLHttpRequest();\r\noReq.addEventListener("load", reqListener);\r\noReq.open("GET", "http://www.reuters.com/");\r\noReq.send();\r\n</script>\r\n</html>
Run Code Online (Sandbox Code Playgroud)\r\n运行它并查看安全错误:
\n\n\n\n\n跨源请求被阻止:同源策略不允许读取http://www.reuters.com/上的远程资源。(原因:CORS 标头\n \xe2\x80\x98Access-Control-Allow-Origin\xe2\x80\x99 丢失)。
\n
Mozilla 对于跨站点 XMLHttpRequest的实现非常清楚:
\n\n\n\n现代浏览器通过实施 Web 应用程序 (WebApps) 工作组的跨站点请求访问控制标准来支持跨站点请求。
\n\n只要服务器配置为允许来自 Web 应用程序源的请求,XMLHttpRequest 就可以工作。否则,将引发\n INVALID_ACCESS_ERR 异常。
\n
归档时间: |
|
查看次数: |
1287 次 |
最近记录: |