Django Rest Framework JWT
Я использую Django Rest Framework для создания API для своего приложения и хотел бы реализовать DjangoRestFramework-JWT для аутентификации токена. Шаги кажутся достаточно простыми, но когда я тестирую конечную точку, я получаю ошибку 500. Вывод терминала - это тонна html, говорящая, что csrf_token не был предоставлен. Код и ошибки ниже. Ваша помощь очень ценится.
curl -X POST -d "username=admin&password=123abc" http://127.0.0.1:8000/api/token/auth/
Ошибка CSRF
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="robots" content="NONE,NOARCHIVE">
<title>403 Forbidden</title>
</head>
<body>
<div id="summary">
<h1>Forbidden <span>(403)</span></h1>
<p>CSRF verification failed. Request aborted.</p>
<p>You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties.</p>
<p>If you have configured your browser to disable cookies, please re-enable them, at least for this site, or for 'same-origin' requests.</p>
</div>
<div id="info">
<h2>Help</h2>
<p>Reason given for failure:</p>
<pre>CSRF cookie not set.</pre>
<p>In general, this can occur when there is a genuine Cross Site Request Forgery, or when <a href="https://docs.djangoproject.com/en/1.8/ref/csrf/">Django's CSRF mechanism</a> has not been used correctly. For POST forms, you need to ensure:</p>
<ul>
<li>Your browser is accepting cookies.</li>
<li>The view function passes a <code>request</code> to the template's <a href="https://docs.djangoproject.com/en/dev/topics/templates/#django.template.backends.base.Template.render"><code>render</code></a> method.</li>
<li>In the template, there is a <code>{% csrf_token %}</code> template tag inside each POST form that targets an internal URL.</li>
<li>If you are not using <code>CsrfViewMiddleware</code>, then you must use <code>csrf_protect</code> on any views that use the <code>csrf_token</code> template tag, as well as those that accept the POST data.</li>
</ul>
<p>You're seeing the help section of this page because you have <code>DEBUG = True</code> in your Django settings file. Change that to <code>False</code>, and only the initial error message will be displayed. </p>
<p>You can customize this page using the CSRF_FAILURE_VIEW setting.</p>
</div>
</body>
</html>
Settings.py
INSTALLED_APPS = (
...
'rest_framework',
...
)
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
}
JWT_AUTH = {
'JWT_RESPONSE_PAYLOAD_HANDLER':
'app.utils.jwt_response_payload_handler',
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=30000),
}
Global Urls.py
urlpatterns = patterns(
...
url(r'^api/auth/token/$', 'rest_framework_jwt.views.obtain_jwt_token'),
url(r'^api/auth/', include('rest_framework.urls', namespace='rest_framework')),
url(r'^api/', include(router.urls)),
)
1 ответ
Вы получаете эту ошибку из-заSessionAuthentication
класс определяется в настройках DRF.
ФПИ SessionAuthentication
использует сессионную структуру Django для аутентификации, которая требует проверки CSRF. DRF обеспечивает проверку CSRF для аутентифицированных пользователей. Это означает, что только для аутентифицированных запросов требуются токены CSRF, а анонимные запросы могут отправляться без токенов CSRF.
Теперь вы делаете запрос от аутентифицированного пользователя и в соответствии с порядком, определенным в DEFAULT_AUTHENTICATION_CLASSES
в settings.py
файл, SessionAuthentication
называется первым. Он проверяет, приходит ли запрос от аутентифицированного пользователя, и если это так, то он должен иметь CSRF
токен, установленный в заголовке запроса. Так как вы не отправляете CSRF Token
в запросе, поэтому он возвращает ошибку.
Вам нужно передать токен CSRF в заголовках при выполнении запроса. Вы можете сделать это через --header/-H
вариант.
--header "X-CSRFToken: {token_value}" # using '--header'
-H "X-CSRFToken: {token_value}" # using '-H'
Вы можете изменить свой запрос на что-то вроде:
curl --header "X-CSRFToken: {token_value}" -X POST -d "username=admin&password=123abc" http://127.0.0.1:8000/api/token/auth/
Другой метод:
Существует еще один вариант, в котором вы можете создать класс пользовательской аутентификации сеанса, который не применяет эту проверку CSRF для аутентифицированных пользователей.
SessionCsrfExemptAuthentication
Приведенный ниже класс не обеспечивает проверку токена CSRF для аутентифицированных пользователей.
from rest_framework.authentication import SessionAuthentication
class SessionCsrfExemptAuthentication(SessionAuthentication):
def enforce_csrf(self, request):
return # To not perform the csrf check previously happening
Затем вы можете определить этот класс аутентификации в ваших настройках, например:
'DEFAULT_AUTHENTICATION_CLASSES': (
# Replace DRF session authentication class with our custom authentication class
'rest_framework.authentication.SessionCsrfExemptAuthentication',
'rest_framework.authentication.BasicAuthentication',
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),