Django rest框架忽略了缺少使用httpie的csrf标记

Vis*_*oru 3 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
Run Code Online (Sandbox Code Playgroud)

哪个成功即使它应该需要CSRF令牌.当我尝试使用以下代码从Chrome中删除对象时:

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

我收到以下请求:

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
Run Code Online (Sandbox Code Playgroud)

响应:

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."}
Run Code Online (Sandbox Code Playgroud)

我的设置:

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',
)
Run Code Online (Sandbox Code Playgroud)

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

Jak*_*cil 5

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

如果你使用SessionAuthentication你需要包括有效的CSRF令牌任何POST,PUT,PATCHDELETE操作.(来源)

我假设您为HTTPie发送的请求使用另一个auth方法,因此CSRF检查不会在那里应用.

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