尽管有 AllowAny 权限,django-rest-framework 在 POST、PUT、DELETE 上返回 403 响应

标签 django authentication permissions django-rest-framework

我正在使用 django-oneall允许在我的网站上进行社交登录 session 身份验证。虽然它不是 django-rest-framework 的建议身份验证提供程序之一,但 rest_framework.authentication.SessionAuthentication使用 django 的默认 session 身份验证。所以我认为集成应该相当简单。
在权限方面,最终我将使用 IsAdmin ,但出于开发目的,我只是将其设置为 IsAuthenticated .当返回 403 时,我将权限放宽到 AllowAny ,但仍然没有骰子。这是我的休息框架配置:
设置.py

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.AllowAny',
        # 'rest_framework.permissions.IsAuthenticated',
        # 'rest_framework.permissions.IsAdminUser',
     ),
    'PAGE_SIZE': 100,
    'DEFAULT_FILTER_BACKENDS': (
        'rest_framework.filters.DjangoFilterBackend',
    ),
}
编辑:
我根据下面的答案得到了这个工作。原来rest_framework期望 csrftoken cookie 和一个 X-CSRFToken相同值的 header ,我设置我的前端代码为所有 ajax 请求发送该 header ,一切正常。

最佳答案

Django REST Framework 返回状态码 403在几个相关情况下:

  • 当您没有所需的权限级别时(例如,当 DEFAULT_PERMISSION_CLASSES('rest_framework.permissions.IsAuthenticated',) 时,以未经身份验证的用户身份发出 API 请求。
  • 当您执行不安全的请求类型(POST、PUT、PATCH 或 DELETE - 应该有副作用的请求)时,您正在使用 rest_framework.authentication.SessionAuthentication并且您没有在请求集中包含您的 CSRFToken。
  • 当您执行不安全的请求类型并且您包含的 CSRFToken 不再有效时。

  • 我将针对测试 API 发出一些演示请求,以给出每个示例,以帮助您诊断您遇到的问题并展示如何解决它。我将使用 requests图书馆。

    测试 API

    我用一个模型设置了一个非常简单的 DRF API,Life ,它包含一个字段( answer ,默认值为 42 )。从现在开始的一切都非常简单。我设置了ModelSerializer - LifeSerializer , 一个 ModelViewSet - LifeViewSet , 和 DefaultRouter/life网址路由。我已将 DRF 配置为要求用户经过身份验证才能使用 API 并使用 SessionAuthentication .

    访问 API
    import json
    import requests
    
    response = requests.get('http://localhost:8000/life/1/')
    # prints (403, '{"detail":"Authentication credentials were not provided."}')
    print response.status_code, response.content
    
    my_session_id = 'mph3eugf0gh5hyzc8glvrt79r2sd6xu6'
    cookies = {}
    cookies['sessionid'] = my_session_id
    response = requests.get('http://localhost:8000/life/1/',
                            cookies=cookies)
    # prints (200, '{"id":1,"answer":42}')
    print response.status_code, response.content
    
    data = json.dumps({'answer': 24})
    headers = {'content-type': 'application/json'}
    response = requests.put('http://localhost:8000/life/1/',
                            data=data, headers=headers,
                            cookies=cookies)
    # prints (403, '{"detail":"CSRF Failed: CSRF cookie not set."}')
    print response.status_code, response.content
    
    # Let's grab a valid csrftoken
    html_response = requests.get('http://localhost:8000/life/1/',
                                 headers={'accept': 'text/html'},
                                 cookies=cookies)
    cookies['csrftoken'] = html_response.cookies['csrftoken']
    response = requests.put('http://localhost:8000/life/1/',
                            data=data, headers=headers,
                            cookies=cookies)
    # prints (403, '{"detail":"CSRF Failed: CSRF token missing or incorrect."}')
    print response.status_code, response.content
    
    headers['X-CSRFToken'] = cookies['csrftoken']
    response = requests.put('http://localhost:8000/life/1/',
                            data=data, headers=headers,
                            cookies=cookies)
    # prints (200, '{"id":1,"answer":24}')
    print response.status_code, response.content
    

    关于尽管有 AllowAny 权限,django-rest-framework 在 POST、PUT、DELETE 上返回 403 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32653518/

    相关文章:

    python - django.db.utils.ProgrammingError : relation "blogango_blog" does not exist

    python - django 从 View 重定向到 iframe 的父级

    python - 如何在 settings.py 中定义常量并在 django 的 View 函数中访问它们

    facebook - 在 Coldfusion 应用程序中使用 Facebook、Google、Yahoo 和 hotmail 登录

    c# - 如何检查我是否可以在特定文件夹中创建文件

    testing - TFS 用户只允许创建错误

    python - 为什么 django-south 不包含在 django.contrib 中?

    java - 2 个不同的 Web 应用程序 - 一个如何识别\验证另一个

    php - Lumen HTTP 基本认证

    django - 潜在的 docker 权限问题导致枕头说它没有安装,尽管它是