我正在使用django-oneall来允许我网站上的社交登录会话身份验证。虽然它不是django-rest-framework的建议auth提供程序之一,但rest_framework.authentication.SessionAuthentication
使用django的默认会话身份验证。所以我认为整合应该相当简单。
在权限方面,最终我将使用IsAdmin
,但出于开发目的,我将其设置为IsAuthenticated
。当返回403时,我放宽了AllowAny
的权限,但仍然没有骰子。这是我的休息框架配置:
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和aa X-CSRFToken
标题具有相同的值,我设置我的前端代码为所有ajax请求发送该标头,一切正常
答案 0 :(得分:24)
Django REST Framework在几个相关情况下返回状态代码403
:
DEFAULT_PERMISSION_CLASSES
为('rest_framework.permissions.IsAuthenticated',)
时,以未经身份验证的用户身份发出API请求。rest_framework.authentication.SessionAuthentication
,并且您没有将CSRFToken包含在requeset中。 我将针对测试API发出一些演示请求,以提供每个示例,以帮助您诊断您遇到的问题并演示如何解决它。我将使用requests
库。
测试API
我使用单个模型Life
设置了一个非常简单的DRF API,其中包含单个字段(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
答案 1 :(得分:1)
为了完整起见,还有一个情况是DRF返回代码403:如果您忘记将as_view()
添加到urls.py文件中的视图声明中。刚发生在我身边,我花了几个小时直到找到问题所在,所以也许这个添加可以节省一些时间。
答案 2 :(得分:0)
仅适用于可能会发现相同问题的任何人。 如果您使用的是没有路由器的视图集,例如:
user_list = UserViewSet.as_view({'get': 'list'})
user_detail = UserViewSet.as_view({'get': 'retrieve'})
除非您在类级别定义Permission_classes,否则Django Rest框架将返回403:
class UserViewSet(viewsets.ModelViewSet):
"""
A viewset for viewing and editing user instances.
"""
permission_classes= YourPermisionClass
希望有帮助!