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),
}

глобальные 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 на , SessionAuthentication вызывается первой. Он проверяет, поступает ли запрос от аутентифицированного пользователя, и если это так, то он должен иметь CSRF набор маркеров в заголовках запросов. Так как вы не посылаете CSRF Token в запросе, поэтому он возвращает ошибку.

вы необходимо передать токен CSRF в заголовках делая запрос. Вы можете сделать это через .

--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',
    ),