简体   繁体   English

Django Rest框架JWT

[英]Django Rest Framework JWT

I'm using Django Rest Framework to build the API for my application and would like to implement DjangoRestFramework-JWT for token authentication. 我正在使用Django Rest Framework为我的应用程序构建API,并想实现DjangoRestFramework-JWT进行令牌身份验证。 The steps seem simple enough but when I test the endpoint I get a 500 error. 步骤似乎很简单,但是当我测试端点时,出现500错误。 The terminal output is a ton of html saying a csrf_token wasn't provided. 终端输出的是大量的HTML,表示未提供csrf_token。 Code & errors are below. 代码和错误如下。 Your help is greatly appreciated. 非常感谢您的帮助。

curl -X POST -d "username=admin&password=123abc" http://127.0.0.1:8000/api/token/auth/

CSRF Error 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 &#39;same-origin&#39; 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 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 全球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)),
)

You are getting this error because of SessionAuthentication class defined in the DRF settings. 由于DRF设置中定义的SessionAuthentication类,导致出现此错误。

DRF's SessionAuthentication uses Django's session framework for authentication which requires CSRF to be checked. DRF的SessionAuthentication使用Django的会话框架进行身份验证,这需要检查CSRF。 DRF enforces CSRF check for authenticated users. DRF对经过身份验证的用户强制执行CSRF检查。 This means that only authenticated requests require CSRF tokens and anonymous requests may be sent without CSRF tokens. 这意味着只有经过身份验证的请求才需要CSRF令牌,并且匿名请求可以在没有CSRF令牌的情况下发送。

Now you are making a request from an authenticated user and as per the order defined in DEFAULT_AUTHENTICATION_CLASSES in the settings.py file, SessionAuthentication is called first. 现在,您正在从经过身份验证的用户发出请求,并按照settings.py文件中DEFAULT_AUTHENTICATION_CLASSES中定义的顺序进行操作,首先调用SessionAuthentication It checks if the request is coming from an authenticated user and if it is, then it must have CSRF token set in the request headers. 它检查请求是否来自经过身份验证的用户,如果是,则必须在请求标头中设置CSRF令牌。 Since you are not sending CSRF Token in the request, so it returns an error. 由于您没有在请求中发送CSRF Token ,因此它返回错误。

You need to pass CSRF Token in the headers while making the request. 发出请求时,您需要在标题中传递CSRF令牌 You can do that via --header/-H option. 您可以通过--header/-H选项来实现。

--header "X-CSRFToken: {token_value}" # using '--header'
-H "X-CSRFToken: {token_value}" # using '-H' 

You can change your request to something like: 您可以将请求更改为以下内容:

curl --header "X-CSRFToken: {token_value}" -X POST -d "username=admin&password=123abc" http://127.0.0.1:8000/api/token/auth/

Another method: 另一种方法:

There is another option where you can create a Custom Session Authentication class which does not enforces this CSRF check for authenticated users. 还有另一个选项,您可以在其中创建“自定义会话身份验证”类,该类不会对经过身份验证的用户强制执行此CSRF检查。

SessionCsrfExemptAuthentication class below does not enforces the CSRF token check for authenticated users. 下面的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

You can then define this authentication class in your settings like: 然后,您可以在设置中定义此身份验证类,例如:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM