Django文档上的CSRF令牌名称与AJAX标头中的变量的实际名称不匹配

时间:2018-08-03 23:06:09

标签: ajax django csrf

我一直在努力发送和接收CSRF令牌,最后我发现Django无法获得令牌值,因为它的名称与文档中推荐的名称不同。为什么?

(我正在HTTPS地址上执行AJAX,并且请求是跨站点的。) Django documentation建议通过以下方式将令牌添加到AJAX标头中:

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});

在这里,名称是X-CSRFToken,它以某种方式变为HTTP_X_CSRFTOKEN。 另一方面,Django正在CSRF_COOKIE下查找cookie。

CsrfViewMiddleware的csrf.py中的第278行:

csrf_token = request.META.get('CSRF_COOKIE')
if csrf_token is None:
# No CSRF cookie. For POST requests, we insist on a CSRF cookie,
# and in this way we can avoid all CSRF attacks, including login
# CSRF.
   return self._reject(request, REASON_NO_CSRF_COOKIE)

我无法更改变量名称,因为出现此错误:

Request header field CSRF_COOKIE is not allowed by Access-Control-Allow-Headers in preflight response.

因此,我最终将源代码中的变量名称从CSRF_COOKIE更改为HTTP_X_CSRFTOKEN。有什么办法可以做到这一点?

(我不执行@csrf_exempt,所以不建议这样做。)

1 个答案:

答案 0 :(得分:0)

问题不在于Django,如果您在此处仔细阅读:https://docs.djangoproject.com/en/2.0/ref/csrf/#how-it-works,您将了解它的工作原理以及遵循的逻辑。

问题是您不允许标题:

[dir] /deep/ .total-deposit_value {
  margin-top: 5px;
}

如果搜索此ACAH,您将发现必须编辑服务器配置文件以允许此类发布。

另一种情况是您可能没有正确发送标头,这就是为什么它在寻找cookie。在这种情况下,您可以尝试将其添加到标题中:

Request header field CSRF_COOKIE is not allowed by Access-Control-Allow-Headers in preflight response.