CORS、Ajax 和 CSRF
Posted
技术标签:
【中文标题】CORS、Ajax 和 CSRF【英文标题】:CORS, Ajax, and CSRF 【发布时间】:2014-03-08 12:51:01 【问题描述】:django 应用程序中的 CSRF 预防支持通过 cookie 将 CSRF 令牌向下发送到客户端,并在标头 (X-CSRFToken) 或 cookie 中接受来自客户端的 CSRF 令牌。这适用于非 CORS、非 AJAX Web 应用程序。但是,如果您 a) 有一个通过 AJAX 与服务器通信的单页 Web 应用程序,并且 b) 单页 Web 应用程序托管在与服务器 (CORS) 不同的域中,则它似乎不起作用。
问题是由于 CORS 限制,单页 webapp(来自 domain1)无法使用 xhr.getResponseHeader 或 getCookie 读取服务器域(domain2)cookie。鉴于无法读取 cookie,javascript webapp 如何将适当的 CSRF 令牌发送到服务器?
xhr.getResponseHeader api 被限制检索 Set-Cookie 或 Set-Cookie2 标头(按规范),并且各种支持 CORS 的浏览器似乎强制执行此限制。同理,getCookie JS 函数会读取 webapp 域(domain1)中所有非 httpOnly cookie,但不会读取服务器在其域(domain2)中设置的那些。
这在非 CORS 情况下不是问题,但在我们的应用程序中,我们希望将 API 托管在与客户端 webapp 不同的域中。有什么建议?
【问题讨论】:
您解决了这个问题吗?听起来你和我有同样的问题。 不,从未解决。 如果这个问题还没解决,可以试试:cistoner.org/blog/minhaz/2014/03/08/… 【参考方案1】:我想我遇到了同样的问题,并通过结合服务器端的东西和客户端的东西来解决它。服务器端(Django-Python):
origin = request.META.get('HTTP_ORIGIN', None)
if origin and origin in settings.safe_origins:
response['Access-Control-Allow-Origin'] = origin
response['Access-Control-Allow-Credentials'] = 'true'
response['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS'
response['Access-Control-Allow-Headers'] = request.META.get('Access-Control-Allow-Headers', 'x-requested-with, X-CSRFToken',)
response['Access-Control-Max-Age'] = 15
response['Allow'] = 'GET, POST, PUT, DELETE, OPTIONS'
客户端启动时:
$.ajaxPrefilter(function(options, originalOptions, jqXHR)
options.crossDomain =
crossDomain: true
;
options.xhrFields =
withCredentials: true
;
);
function csrfSafeMethod(method)
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
$.ajaxSetup(
crossDomain: false, // obviates need for sameOrigin test
beforeSend: function(xhr, settings)
if (!csrfSafeMethod(settings.type))
xhr.setRequestHeader("X-CSRFToken", csrf);
);
然后在 $.ajax 中调用它们自己:
$.ajax(
type: "POST",
url: theUrl,
data: theData,
contentType: 'application/x-www-form-urlencoded',
dataType: 'json',
xhrFields:
withCredentials: true
);
对我来说,我最想念的就是这部分:
xhrFields:
withCredentials: true
希望这对某人有所帮助。
【讨论】:
有趣。我相信我们正在做你上面描述的所有事情,除了在 ajax 请求中设置 crossDomain: false 。我认为我们已经明确设置了 crossDomain: true。我会调查一下。谢谢。以上是关于CORS、Ajax 和 CSRF的主要内容,如果未能解决你的问题,请参考以下文章
CORS $.ajax 会话 cookie(访问控制允许凭据和 withCredentials=true)
AJAX、CORS、Chrome 和 HTTP 错误代码 (401,403,404,500) 的推荐解决方案
如何使用 Web 服务和 jQuery Ajax 启用 CORS