django JWT认证(二)

我们在DRF前后端分离的情况使用django-rest-framework-jwt 这个包,这个包需要单独安装。它支持

  • Python (2.7, 3.3, 3.4, 3.5, 3.6)
  • Django (1.8, 1.9, 1.10, 1.11) # 2.0设置也是没有问题的
  • Django REST Framework (3.1, 3.2, 3.3, 3.4, 3.5, 3.6)

安装

使用pip安装

1
pip install djangorestframework-jwt

配置

安装完jwt后需要settings.py设置

1
2
3
4
5
6
7
8
9
10
11
12
13

REST_FRAMEWORK = {
# 设置所有接口都需要被验证
'DEFAULT_PERMISSION_CLASSES': (
#'rest_framework.permissions.IsAuthenticated', 建议是特定接口特定认证
),
# 用户登陆认证方式
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}

修改urls.py

1
2
3
4
5
6
7
8

from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path(r"login", obtain_jwt_token),
]

测试访问

返回的就是用户的token数据,前端获取到该token存储后携带上,默认token有效期为5分钟

解析token

客户端请求

在headers中带上Authorization JWT <token>
以postman为例

如果没有携带后端会提示以下信息

1
2
3
{
"detail": "Authentication credentials were not provided."
}

JWT设置

1
2
3
4
5
6
7
8
9
10
11
12
13

JWT_AUTH = {
# 设置token 有效期
'JWT_EXPIRATION_DELTA': datetime.timedelta(hours=24),
#续期有效期(该设置可在24小时内带未失效的token 进行续期)
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(hours=24),
# 自定义返回格式,需要手工创建
'JWT_RESPONSE_PAYLOAD_HANDLER': 'utils.jwt.jwt_response_payload_handler',
# 用于令牌和授权标头的另一个常见值是Bearer ,默认是JWT
'JWT_AUTH_HEADER_PREFIX': 'Token:',
# 是否允许刷新
'JWT_ALLOW_REFRESH': True
}

更详细设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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': settings.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': False,
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),

'JWT_AUTH_HEADER_PREFIX': 'JWT',
'JWT_AUTH_COOKIE': None,

}

自定义返回数据

在utils目录下创建jwt.py文件

1
2
3
4
5
6
7
8
9
10

def jwt_response_payload_handler(token, user=None, request=None, role=None):
return {
"authenticated": "true",
'id': user.id,
"role": role,
'username': user.username,
'email': user.email,
'token': token,
}

请求

1
2
3
4
5
6
7
8
{
"authenticated": "true",
"id": 1,
"role": null,
"username": "admin",
"email": "923401910@qq.com",
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNTkyNjI3ODk3LCJlbWFpbCI6IjkyMzQwMTkxMEBxcS5jb20iLCJvcmlnX2lhdCI6MTU5MjU0MTQ5N30.YBDrPiz0wX6i0lrQwqb5bbHf8wgEIPk5Si598jHQW1A"
}

token 续期

urls.py中加入refresh

1
2
3
4
5
6
7
8
9
from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token
from django.contrib import admin
from django.urls import path, include
from music.views import MusicListView
urlpatterns = [
path('login/', obtain_jwt_token),
path('refresh/', refresh_jwt_token),
path('music/', MusicListView.as_view()),
]

请求使用POST方法并且在BODY中带入token数据

测试代码

参考