CSRF 失败:CSRF 令牌丢失或不正确
Posted
技术标签:
【中文标题】CSRF 失败:CSRF 令牌丢失或不正确【英文标题】:CSRF Failed: CSRF token missing or incorrect 【发布时间】:2014-12-25 16:16:10 【问题描述】:我正在使用 Django 1.7 和 django-rest-framework。
我创建了一个 API,它返回一些 JSON 数据,并将其放入我的 settings.py
REST_FRAMEWORK =
'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.AllowAny',),
'DEFAULT_RENDERER_CLASSES': (
# 'rest_framework.renderers.XMLRenderer',
'rest_framework.renderers.JSONRenderer',
# 'rest_framework.renderers.BrowsableAPIRenderer',
)
当我进行 GET 调用时,它会返回所有数据,但是当我尝试使用 PUT/PATCH 时,我会得到:
--------Response Headers---------
Status Code: 403
Date: Wed, 29 Oct 2014 18:51:42 GMT
Vary: Cookie
Server: WSGIServer/0.1 Python/2.7.8
Allow: GET, POST, PUT, PATCH, HEAD, OPTIONS
X-Frame-Options: SAMEORIGIN
Content-Type: application/json
---------------------------------
--------Response Body-----------
"detail": "CSRF Failed: CSRF token missing or incorrect."
---------------------------------
这仅在我登录时发生,如果我是匿名的,我可以正确 PUT/PATCH。
我已尝试使用@csrf_exempt
,但出现错误,我已将rest_framework.permissions.AllowAny
包含在设置中...
我不知道发生了什么。有谁知道是什么问题?
【问题讨论】:
【参考方案1】:当您使用SessionAuthentication 时,您使用的是 Django 的身份验证,这通常需要检查 CSRF。 Django REST Framework 强制执行此操作,仅针对 SessionAuthentication
,因此您必须在 X-CSRFToken
标头中传递 CSRF 令牌。
Django documentation 提供了有关使用 jQuery 检索 CSRF 令牌并在请求中发送它的更多信息。 CSRF 令牌保存为一个名为 csrftoken
的 cookie,您可以从 HTTP 响应中检索它,具体取决于所使用的语言。
如果您无法检索 CSRF cookie,这通常表明您不应该使用 SessionAuthentication
。我建议根据您的需要查看TokenAuthentication 或OAuth 2.0。
【讨论】:
我知道我应该在通过身份验证时提供 CSRF 令牌,但是,实际上我正在使用 .NET Windows 窗体应用程序与此 API 通信,它通过 HTTPRequest 和 HTTPResponse 方法进行 GET 调用,我不知道在这种情况下如何获得 CSRF 令牌,我没有使用 AJAX 或 html 表单。 编辑 .NET 应用程序接收 JSON 格式的纯文本,并返回相同的内容 你没事,我可以使用 cookie 处理 csrftoken 并将其放回标头数据中,这样我就可以在登录时进行 PUT/PATCH 调用。谢谢! @AlexLordMordor 你能解释一下你的解决方案吗?以及为什么当您是登录用户时它不起作用,但以匿名方式起作用。 (我有完全相同的问题) 当您使用 SessionAuthentication 时,默认情况下 django 需要两个“密钥”,其中一个可以在登录用户处于活动状态时在 cookie 中找到,另一个是 csrf-token,如果他们这样做的话不匹配,然后引发错误,因此,有像 @Kevin 这样的文档说要以正确的方式进行身份验证。 另一种实现方式可以在这篇文章中找到:blog.kevinastone.com/…,在“插曲:AngularJS + CSRF 保护”部分。在这种情况下使用 AngularJS【参考方案2】:这就是我为解决它所做的,我在表单中包含了 csrf 令牌,并在加载文档时使用 jquery/javascrip 得到了这样的 csrf 令牌
var $crf_token = $('[name="csrfmiddlewaretoken"]').attr('value');
将其包含在 jquery 标头中,如下所示
$.ajax(
type: "POST",
url: "/api/endpoint/",
data: newEndpoint,
headers:"X-CSRFToken": $crf_token,
success: function (newEnd)
console.log(newEnd);
add_end(newEnd);
,
error: function ()
alert("There was an error")
);
【讨论】:
这行得通。如果有人想知道,$crf_token 的值来自基本身份验证登录期间拾取的 csrftoken cookie。【参考方案3】:我认为这是一个 cookie 问题。
永久解决方案:如果您使用的是 Postman,首先,通过单击“X”清除现有的 cookie。然后添加正确的cookie。
临时解决方案(用于调试):在您的 settings.py
中试试这个:
'DEFAULT_AUTHENTICATION_CLASSES': [
# 'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
]
【讨论】:
清除 cookie 解决了我的问题【参考方案4】:1- 搜索 Cookie 标头
2- 将 csrftoken 与 sessionid 分开
3- 添加 X-CSRFToken=..the csrftoken that you extract in step 2.. 见下文
4- 再次发帖
【讨论】:
【参考方案5】:我们遇到了这个问题,结果证明是 Postman 的错。他们自动发送csrftoken
和sessionid
默认值,我们没有在标头中传递这些值。按照本教程帮助解决了这个问题:https://avilpage.com/2019/02/django-tips-csrf-token-postman-curl.html
【讨论】:
【参考方案6】:解决此错误的最简单方法,我在here 上找到。它非常适合我。
步骤:
继承 SessionAuthentication 类:
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
class CsrfExemptSessionAuthentication(SessionAuthentication):
def enforce_csrf(self, request):
return # To not perform the csrf check previously happening
然后在您创建的 APIView 中,执行以下操作:
class Object(APIView):
authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication)
def post(self, request, format=None):
这将使您保持登录状态,并且您的 CSRF 令牌将不再检查此 APIView。
【讨论】:
你已经向 CSRF 攻击敞开了大门。【参考方案7】:我遇到了类似的问题,我已经将我的网址包装在 csrf_exempt
方法下 -
from django.views.decorators.csrf import csrf_exempt
url(r'^api/v1/some-resource$', csrf_exempt(SomeApiView.as_view())),
【讨论】:
【参考方案8】:对我有用的最简单的解决方案是:
在 AJAX POST 调用的标头中添加 CSRF 令牌,这可以通过包含这一行代码来完成
headers: "X-CSRFToken": 'csrf_token' ,
这行应该加在success
上面
【讨论】:
【参考方案9】:从 cookie 中获取令牌:
function readCookie(name)
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++)
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
return null;
var csrftoken = readCookie('csrftoken');
在标头 POST 请求中发送令牌:
this.$http.post(server,params: foo: 'bar', headers: "X-CSRFToken":csrftoken ).then(function (response)
this.response = response.data;
,
function (response)
console.log(response);
);
【讨论】:
这是唯一有实际代码的有效答案。【参考方案10】:我遇到了类似的问题,我用csrf_exempt
包装了视图,但仍然遇到错误。结果发现我弄错了 URL,所以它被解析为“未找到”回调(CSRF 并没有豁免),因此在我被告知 URL 错误之前抛出了一个异常。
【讨论】:
对我来说,我只是忘记在我的 URL 中添加结尾的“/”。就像@kokociel 所说,这个问题与 CSRF 无关,而是 URL 没有解析到我的任何端点。【参考方案11】:// USING AJAX TO UPDATE DATABASE THROUGH REST API
function getCookie(name)
var cookieValue = null;
if (document.cookie && document.cookie !== '')
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++)
var cookie = jQuery.trim(cookies[i]);
if (cookie.substring(0, name.length + 1) === (name + '='))
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
return cookieValue;
var csrftoken = getCookie('csrftoken');
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);
);
【讨论】:
【参考方案12】:这发生在我使用邮递员测试 rest-auth 注册时 发生这种情况是因为邮递员发送了错误的标头,一些旧的 cookie 和错误的内容类型,我认为这是某种错误,或者我错了
解决方案:所以我禁用了默认标题
手动输入的内容类型和json正文(POST请求)
然后重新启用所需的标头
【讨论】:
【参考方案13】:当您在 Apache 服务器上托管 django 网站时。 带有 TokenAuthentication 和 SessionAuthentication 的 Django REST 框架将得到 p>
CSRF 失败:CSRF 令牌丢失或不正确
要修复这个打开的 Apache 配置文件 - httpd.conf 添加以下行:
WSGIPassAuthorization On
【讨论】:
【参考方案14】:在settings.py文件中
INSTALLED_APPS = [
...
...
...
...
'rest_framework.authtoken',
...
]
REST_FRAMEWORK =
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
在项目 urls.py 中
from rest_framework.authtoken import views
urlpatterns = [
....
path('api-token-auth/',views.obtain_auth_token,name='api-token-auth')
]
打开终端
$ pip3 install httpie
$ python3 manage.py createsuperuser # if not created
$ http POST http://localhost:8000/api-token-auth/ username="username" password = "password" # You will get token key (Just copy it) ex:a243re43fdeg7r4rfgedwe89320
您的令牌密钥也将自动保存在您的数据库中
转到邮递员标题(如示例) 例如:screenshot from postman ,where and how to paste accessed toke
然后插入你的令牌密钥。
You can take reference to get token key from this video
【讨论】:
【参考方案15】:我在 postman 中测试 API 时遇到了同样的问题,我通过在 Postman 中为该请求清理缓存解决了这个问题。
【讨论】:
【参考方案16】:django1.8 python2.7
"detail": "CSRF Failed: CSRF token missing or incorrect."
我通过使用其他 http 方法来修复它; 哦,我又面对了,这次是因为我粘贴了,有一些看不见的字符
【讨论】:
Here are a few tips on how to make your answer great以上是关于CSRF 失败:CSRF 令牌丢失或不正确的主要内容,如果未能解决你的问题,请参考以下文章
Django - 403 禁止。 CSRF 令牌丢失或不正确
Django Rest Framework,ajax POST 工作,但 PATCH 抛出 CSRF 失败:CSRF 令牌丢失或不正确