django应用程序中的CSRF预防支持通过cookie将CSRF令牌发送到客户端,并通过标头(X-CSRFToken)或cookie从客户端接受CSRF令牌。这适用于非CORS,非AJAX Web应用程序。但是,如果你a)拥有一个通过AJAX与服务器通信的单页Web应用程序,并且b)单页webapp托管在与服务器(CORS)不同的域中,那么它似乎不起作用。
问题在于,由于CORS限制,单页webapp(来自domain1)无法使用xhr.getResponseHeader或getCookie读取服务器域(domain2)cookie。 javascript webapp如何将适当的CSRF令牌发送到服务器,因为它无法读取cookie?
xhr.getResponseHeader api被限制检索Set-Cookie或Set-Cookie2标头(按规范),并且各种支持CORS的浏览器似乎强制执行此限制。类似地,getCookie JS函数将读取webapp域(domain1)中的所有非httpOnly cookie,但不会读取服务器在其域(domain2)中设置的cookie。
这在非CORS情况下不是问题,但在我们的应用程序中,我们希望在与客户端webapp不同的域中托管API。有什么建议?
答案 0 :(得分:0)
我当时正在做同样的事情,这让我很生气。我正在使用MVC WEB API,但我认为有类似的东西会阻止你。
我的问题至少是OPTIONS调用服务器检查服务器是否允许发送自定义标头失败,因此从未进行实际的GET / POST调用。您必须覆盖服务器上的选项请求以允许此操作。当然,允许从您呼叫的站点到服务器的orgin。
以下是一篇关于ASP.NET的文章,但我认为这有助于您理解该问题,即使它是ASP.NET。
http://www.jefclaes.be/2012/09/supporting-options-verb-in-aspnet-web.html
希望这有帮助。
答案 1 :(得分:0)
我认为我遇到了同样的问题,并通过服务器端的东西和客户端的东西来解决它。服务器端(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
}
希望这有助于某人。