python - Django rest 框架使用 httpie 忽略丢失的 csrf token

标签 python django rest django-rest-framework

我正在使用 httpie玩我用 django 1.7 和 django rest framework 2.4 编写的 api。 今天我试图删除一个对象:

$ http DELETE :8000/api/items/8/ --verbose
DELETE /api/items/8/ HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, compress
Content-Length: 0
Host: 127.0.0.1:8000
User-Agent: HTTPie/0.8.0


HTTP/1.0 204 NO CONTENT
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Language: cs
Content-Length: 0
Date: Wed, 07 Jan 2015 21:47:06 GMT
Server: WSGIServer/0.1 Python/2.7.6
Vary: Accept, Accept-Language, Cookie

虽然需要 CSRF token ,但还是成功了。当我尝试使用以下代码从 Chrome 中删除对象时:

$.ajax({
    type: "DELETE",
    url: "http://127.0.0.1:8000/api/items/6/"
});

我收到以下请求:

DELETE /api/items/6/ HTTP/1.1
Host: 127.0.0.1:8000
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept: */*
Origin: http://127.0.0.1:8000
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
DNT: 1
Referer: http://127.0.0.1:8000/inventory
Accept-Encoding: gzip, deflate, sdch
Accept-Language: cs,en-US;q=0.8,en;q=0.6,es;q=0.4,pt;q=0.2,sk;q=0.2
Cookie: cc_csrf=bd9fbbc8f75cffa2e1e3d2c95c2185c5; _ga=GA1.1.2038400685.1386436341; __utma=96992031.2038400685.1386436341.1417173095.1417428975.79; __utmz=96992031.1409752584.3.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __zlcmid=MpdRtV3vZuf3D9; djdt=hide; sessionid=kiihjh6m77jm8v9ol7xrryip89sny55i; csrftoken=FtnnEWPLhMh0CAGMRMH77nB0AAno93uW

响应:

HTTP/1.0 403 FORBIDDEN
Date: Wed, 07 Jan 2015 21:57:40 GMT
Server: WSGIServer/0.1 Python/2.7.6
Vary: Accept, Accept-Language, Cookie
Content-Type: application/json
Content-Language: en
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS

{"detail": "CSRF Failed: CSRF token missing or incorrect."}

我的设置:

REST_FRAMEWORK = {
    # Use hyperlinked styles by default.
    # Only used if the `serializer_class` attribute is not set on a view.
    'DEFAULT_MODEL_SERIALIZER_CLASS': 'rest_framework.serializers.HyperlinkedModelSerializer',

    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    ],

    'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',),
    'DATETIME_FORMAT': "%B %d, %Y"
}
MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'debug_toolbar.middleware.DebugToolbarMiddleware',
)

所以我的问题是:使用 JS ajax 发送 DELETE 请求和使用 http 发送请求有什么区别?

最佳答案

这是因为 CSRF 检查仅在使用 SessionAuthentication 进行身份验证时执行,(即使用 django.contrib.auth 设置的 sessionid cookie ):

If you're using SessionAuthentication you'll need to include valid CSRF tokens for any POST, PUT, PATCH or DELETE operations. (source)

我假设您对 HTTPie 发送的请求使用了另一种身份验证方法,因此 CSRF 检查不会在那里应用。

https://github.com/tomchristie/django-rest-framework/blob/master/tests/test_authentication.py

关于python - Django rest 框架使用 httpie 忽略丢失的 csrf token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27829413/

相关文章:

Django - 多态模型还是一个大模型?

django - 在将 APIView 与 django-rest-swagger 一起使用时,如何指定 POST 请求的参数

javascript - Ajax xml 调用、Dynatrace 仪表板的权限被拒绝

python - 将列表转换为 svm 输入

python - 为什么 Selenium (Python) 无法在带有链接文本的页面上找到链接?

python - 如何使用带有数据的数据库在 Django 中运行测试?

api - 404 是否是当前不存在的资源的正确返回代码?

python - 如何在笔记本中绘制 keras 激活函数

python - 如何使用.join?

java - 对公共(public)和私有(private)资源使用不同的路径 Jersey + Spring boot