简介
Django REST框架的JSON Web Token认证插件。
安装
1 | pip install djangorestframework-simplejwt |
如打算使用数字签名算法对令牌进行编码或解码,需要额外安装djangorestframework-simplejwt[crypto]
。
项目配置
Django项目需要配置使用该库,添加 rest_framework_simplejwt.authentication.JWTAuthentication到身份验证类列表。
1
2
3
4
5
6
7
8REST_FRAMEWORK = {
...
'DEFAULT_AUTHENTICATION_CLASSES': (
...
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
...
}添加获取token和刷新token接口到项目urls.py。
1
2
3
4
5
6
7
8
9
10
11from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns = [
...
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
...
]配置SIMPLE_JWT,添加到settings.py。
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
36
37
38
39
40
41
42
43
44SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": timedelta(hours=2), # 访问令牌有效时间
"REFRESH_TOKEN_LIFETIME": timedelta(days=7), # 刷新令牌有效时间
"ROTATE_REFRESH_TOKENS": True, # 若为True,刷新时refresh_token也会刷新
"BLACKLIST_AFTER_ROTATION": True, # 若为True,刷新后的token将添加到黑名单中
"UPDATE_LAST_LOGIN": False, # 是否更新auth_user 表中的 last_login 字段
"ALGORITHM": "HS256", # 加密算法
"SIGNING_KEY": SECRET_KEY, # 签名密钥
"VERIFYING_KEY": "", # 验证密钥,加密算法指定HMAC时被忽略
"AUDIENCE": None, # 生成的令牌中和/或在解码的令牌中验证的受众主张。当设置为 "无 "时,该字段被排除在令牌之外,并且不被验证。
"ISSUER": None, # 生成的令牌中和/或在解码的令牌中验证的发行者主张。当设置为 "无 "时,该字段被排除在令牌之外,并且不被验证。
"JSON_ENCODER": None,
"JWK_URL": None, # JWK_URL用于动态解析验证令牌签名所需的公钥
"LEEWAY": timedelta(seconds=60), # 令牌过期回旋时间
"AUTH_HEADER_TYPES": ("Bearer",), # 需要认证的视图所接受的授权头类型
"AUTH_HEADER_NAME": "HTTP_AUTHORIZATION", # 用于认证的授权标头名称
"USER_ID_FIELD": "id", # 指定识别用户的字段
"USER_ID_CLAIM": "user_id", # 存储用户标识符
# 确定用户是否被允许进行认证规则
"USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule",
"AUTH_TOKEN_CLASSES": (
"rest_framework_simplejwt.tokens.AccessToken",
# "rest_framework_simplejwt.tokens.SlidingToken"
), # 允许用来证明认证的令牌类型
"TOKEN_TYPE_CLAIM": "token_type", # 存储令牌类型的名称
# 一个无状态的用户对象,由一个经过验证的令牌支持。仅用于JWTStatelessUserAuthentication认证后端。
"TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser",
"JTI_CLAIM": "jti", # 存储一个令牌的唯一标识符的声称名称
"SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp", # 存储滑动令牌刷新期的过期时间的名称
"SLIDING_TOKEN_LIFETIME": timedelta(minutes=5), # 滑动令牌的有效时间
"SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1), # 指定了可以刷新滑动令牌的有效时间
"TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainPairSerializer",
"TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSerializer",
"TOKEN_VERIFY_SERIALIZER": "rest_framework_simplejwt.serializers.TokenVerifySerializer",
"TOKEN_BLACKLIST_SERIALIZER": "rest_framework_simplejwt.serializers.TokenBlacklistSerializer",
"SLIDING_TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainSlidingSerializer",
"SLIDING_TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSlidingSerializer",
}如果允许用户在无需访问签名密钥情况下验证HMAC签名的令牌,需要添加认证接口。
1
2
3
4
5
6
7from rest_framework_simplejwt.views import TokenVerifyView
urlpatterns = [
...
path('api/token/verify/', TokenVerifyView.as_view(), name='token_verify'),
...
]如果你希望使用本地化或翻译,需要添加
rest_framework_jwt
到INSTALLED_APPS
。1
2
3
4
5INSTALLED_APPS = [
...
'rest_framework_simplejwt',
...
]
测试
发送测试请求。
1
2
3
4
5
6
7
8
9
10
11curl \
-X POST \
-H "Content-Type: application/json" \
-d '{"username": "davidattenborough", "password": "boatymcboatface"}' \
http://localhost:8000/api/token/
...
{
"access":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiY29sZF9zdHVmZiI6IuKYgyIsImV4cCI6MTIzNDU2LCJqdGkiOiJmZDJmOWQ1ZTFhN2M0MmU4OTQ5MzVlMzYyYmNhOGJjYSJ9.NHlztMGER7UADHZJlxNG0WSi22a2KaYSfd1S-AuT7lU",
"refresh":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImNvbGRfc3R1ZmYiOiLimIMiLCJleHAiOjIzNDU2NywianRpIjoiZGUxMmY0ZTY3MDY4NDI3ODg5ZjE1YWMyNzcwZGEwNTEifQ.aEoAYkSJjoWH1boshQAaTkf8G3yn0kapko6HFRt7Rh4"
}使用access访问受保护的视图。
1
2
3curl \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiY29sZF9zdHVmZiI6IuKYgyIsImV4cCI6MTIzNDU2LCJqdGkiOiJmZDJmOWQ1ZTFhN2M0MmU4OTQ5MzVlMzYyYmNhOGJjYSJ9.NHlztMGER7UADHZJlxNG0WSi22a2KaYSfd1S-AuT7lU" \
http://localhost:8000/api/some-protected-view/当access过期时,使用refresh来获取另一个access。
1
2
3
4
5
6
7
8curl \
-X POST \
-H "Content-Type: application/json" \
-d '{"refresh":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImNvbGRfc3R1ZmYiOiLimIMiLCJleHAiOjIzNDU2NywianRpIjoiZGUxMmY0ZTY3MDY4NDI3ODg5ZjE1YWMyNzcwZGEwNTEifQ.aEoAYkSJjoWH1boshQAaTkf8G3yn0kapko6HFRt7Rh4"}' \
http://localhost:8000/api/token/refresh/
...
{"access":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiY29sZF9zdHVmZiI6IuKYgyIsImV4cCI6MTIzNTY3LCJqdGkiOiJjNzE4ZTVkNjgzZWQ0NTQyYTU0NWJkM2VmMGI0ZGQ0ZSJ9.ekxRxgb9OKmHkfy-zs1Ro_xs1eMLXiR17dIDBVxeT-w"}
自定义令牌声明
手动创建令牌
如果需要为用户手动创建令牌,可按如下方式完成。
1 | from rest_framework_simplejwt.tokens import RefreshToken |
上面的函数get_tokens_for_user将返回给定用户的新刷新和访问令牌的序列化表示。
一般来说,任何 rest_framework_simplejwt.tokens.Token 子类的令牌都可以通过这种方式创建。
令牌类型
simplejwt提供了两种不同的令牌类型用于认证。令牌的类型通过令牌载荷中
滑动令牌
黑名单应用
无状态用户认证
JwtStatelessUserAuthentication后端认证方法并不执行数据库查询来获得一个数据库实例,相反,它返回一个
rest_framework_simplejwt.models.TokenUser实例,作为一个无状态用户对象,只由一个经过验证的令牌支持,而不是数据库中的记录。他可以开发单独托管的Django应用程序之间的单点登录功能,这些应用程序都共享相同的令牌密钥。要使用这个功能,需要在DjangoREST框架中的DEFAULT_AUTHENTICATION_CLASSES配置设置中添加rest_framework_simplejwt.authentication