带有 jwt 身份验证的 django rest api 要求 csrf 令牌
Posted
技术标签:
【中文标题】带有 jwt 身份验证的 django rest api 要求 csrf 令牌【英文标题】:django rest api with jwt authentication is asking for csrf token 【发布时间】:2018-06-22 16:08:10 【问题描述】:我是 django rest api 框架的新手。我正在为其余 api 使用基于 JWT 令牌的身份验证,并具有以下设置 -
REST_FRAMEWORK =
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
AND
JWT_AUTH =
'JWT_ENCODE_HANDLER':
'rest_framework_jwt.utils.jwt_encode_handler',
'JWT_DECODE_HANDLER':
'rest_framework_jwt.utils.jwt_decode_handler',
'JWT_PAYLOAD_HANDLER':
'rest_framework_jwt.utils.jwt_payload_handler',
'JWT_PAYLOAD_GET_USER_ID_HANDLER':
'rest_framework_jwt.utils.jwt_get_user_id_from_payload_handler',
'JWT_RESPONSE_PAYLOAD_HANDLER':
'rest_framework_jwt.utils.jwt_response_payload_handler',
'JWT_SECRET_KEY': SECRET_KEY,
'JWT_GET_USER_SECRET_KEY': None,
'JWT_PUBLIC_KEY': None,
'JWT_PRIVATE_KEY': None,
'JWT_ALGORITHM': 'HS256',
'JWT_VERIFY': True,
'JWT_VERIFY_EXPIRATION': True,
'JWT_LEEWAY': 0,
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300),
'JWT_AUDIENCE': None,
'JWT_ISSUER': None,
'JWT_ALLOW_REFRESH': True,
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
'JWT_AUTH_HEADER_PREFIX': ('JWT','Bearer'),
'JWT_AUTH_COOKIE': None,
现在基于此,我在 chrome 中使用了 postman 插件,并尝试使用以下步骤测试我的 web api 进行身份验证 -
我使用带有凭据的 url http://127.0.0.1:8000/webs/auth-jwt/ 来获取令牌。
我使用了 url http://127.0.0.1:8000/webs/testspsearch/ 并将步骤 1 中生成的令牌作为 Authorization Bearer 传递。这被定义为 POST 方法
但是当我这样做时,我得到了错误 -> CSRF 验证失败。请求中止。 HTTP 403 错误。
你能告诉我我在这方面做错了什么吗?
【问题讨论】:
请记住,如果您从“127.0.0.1:8000”以外的任何地方向您的 api 发送请求,则(同源策略)[en.wikipedia.org/wiki/Same_origin_policy] 将生效并阻止请求(标准 CSRF 端口)。请注意,即使是在 localhost 但在不同端口上运行的 Web 前端也会被视为不同的来源。您需要启用 CORS 才能使其正常工作,例如下面提到的 @Muhammad Hassan。 【参考方案1】:因为您是从提供数据的同一台机器发出请求,这将(相当烦人)导致 CSRF 异常。您需要在请求中包含一个 CSRF 令牌 cookie,以表明请求正常。
所以你可以做以下两件事之一:
使端点crsf 豁免 (推荐)获取 crsf 令牌并将其作为标头附加到您的 HTTP POST 请求中CSRF 豁免
您可以通过添加装饰器使各种端点 csrf 豁免
from django.views.decorators.csrf import csrf_exempt
class SomeView(APIView):
@csrf_exempt
def post(self, request):
serializer = RegisterUserSerializer(data=request.data)
请求令牌
这有点麻烦(在我看来),因为你必须使用 javascript:
// using jQuery
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]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '='))
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
return cookieValue;
var csrftoken = getCookie('csrftoken');
For more info check the docs
【讨论】:
【参考方案2】:使用django-cors-middleware 允许跨源请求。步骤如下
-
在已安装的应用中添加
corsheaders
在中间件中添加corsheaders.middleware.CorsMiddleware
。
在设置中添加CORS_ORIGIN_ALLOW_ALL = False
。
更多设置可见文档。
【讨论】:
以上是关于带有 jwt 身份验证的 django rest api 要求 csrf 令牌的主要内容,如果未能解决你的问题,请参考以下文章
Django Rest Framework JWT 未提供身份验证凭据
JSON:带有 django-rest-framework-json-api 和 JWT 的 API
Django Rest Framework 中的 JWT 身份验证错误“无效签名”