Django: DjangoRestFramework 使用 simpleJWT 登陆认证完整记录
本文为 djangorestframework-simplejwt 使用记录。(官方文档)
1. 安装
pip install djangorestframework - simplejwt |
2. 使用
创建 Django 项目及 app:
# 创建名为 simple 的工程 django - admin startproject simple # 创建名为 users 的应用 cd simple python manage.py startapp users |
目录结构如下:
在 `simple/settings.py` 中进行配置:
# simple/settings.py INSTALLED_APPS = [ 'django.contrib.admin' , 'django.contrib.auth' , 'django.contrib.contenttypes' , 'django.contrib.sessions' , 'django.contrib.messages' , 'django.contrib.staticfiles' , 'users' , # add 'rest_framework' , # add 'rest_framework_simplejwt' , # add ] REST_FRAMEWORK = { # add 'DEFAULT_AUTHENTICATION_CLASSES' : ( 'rest_framework_simplejwt.authentication.JWTAuthentication' , ) } |
同步数据库并创建超级用户:
# 同步数据库 python manage.py makemigrations python manage.py migrate # 创建超级用户 python manage.py createsuperuser |
在 `simple/urls.py` 中编写路由:
# simple/urls.py from django.contrib import admin from django.urls import path from rest_framework_simplejwt.views import TokenRefreshView, TokenVerifyView, TokenObtainPairView urlpatterns = [ path( 'admin/' , admin.site.urls), path( 'login/' , TokenObtainPairView.as_view(), name = 'token_obtain_pair' ), path( 'refresh/' , TokenRefreshView.as_view(), name = 'token_refresh' ), path( 'verify/' , TokenVerifyView.as_view(), name = 'token_verify' ), ] |
使用 python http 工具进行接口测试:
http -f POST http://127.0.0.1:8000/login/ username=admin password=123456
3. 测试 API 接口
在 `users/views.py` 中编写如下代码:
# users/views.py from rest_framework import permissions from rest_framework.response import Response from rest_framework.views import APIView class MyView(APIView): permission_classes = [permissions.IsAuthenticated] def get( self , request, * args, * * kwargs): return Response( "Get information successfully!" ) |
然后在 `simple/urls.py` 中添加路由:
# simple/urls.py from users import views # add urlpatterns = [ ... path( 'info/' , views.MyView.as_view()), # add ] |
使用 python http 工具进行测试:
4. 配置相关
# settings.py from datetime import timedelta SIMPLE_JWT = { 'ACCESS_TOKEN_LIFETIME' : timedelta(minutes = 5 ), # 访问令牌的有效时间 'REFRESH_TOKEN_LIFETIME' : timedelta(days = 1 ), # 刷新令牌的有效时间 'ROTATE_REFRESH_TOKENS' : False , # 若为True,则刷新后新的refresh_token有更新的有效时间 'BLACKLIST_AFTER_ROTATION' : True , # 若为True,刷新后的token将添加到黑名单中, # When True,'rest_framework_simplejwt.token_blacklist',should add to INSTALLED_APPS 'ALGORITHM' : 'HS256' , # 对称算法:HS256 HS384 HS512 非对称算法:RSA 'SIGNING_KEY' : SECRET_KEY, 'VERIFYING_KEY' : None , # if signing_key, verifying_key will be ignore. 'AUDIENCE' : None , 'ISSUER' : None , 'AUTH_HEADER_TYPES' : ( 'Bearer' ,), # Authorization: Bearer 'AUTH_HEADER_NAME' : 'HTTP_AUTHORIZATION' , # if HTTP_X_ACCESS_TOKEN, X_ACCESS_TOKEN: Bearer 'USER_ID_FIELD' : 'id' , # 使用唯一不变的数据库字段,将包含在生成的令牌中以标识用户 'USER_ID_CLAIM' : 'user_id' , # 'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',), # default: access # 'TOKEN_TYPE_CLAIM': 'token_type', # 用于存储令牌唯一标识符的声明名称 value:'access','sliding','refresh' # # 'JTI_CLAIM': 'jti', # # 'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp', # 滑动令牌是既包含到期声明又包含刷新到期声明的令牌 # 'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5), # 只要滑动令牌的到期声明中的时间戳未通过,就可以用来证明身份验证 # 'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1), # path('token|refresh', TokenObtainSlidingView.as_view()) } |
5. 自定义返回 token 信息
在 `users/serializers.py` 中编写如下代码:
# simple/serializers.py from rest_framework_simplejwt.serializers import TokenObtainPairSerializer class MyTokenObtainPairSerializer(TokenObtainPairSerializer): def validate( self , attrs): data = super ().validate(attrs) refresh = self .get_token( self .user) data[ 'refresh' ] = str (refresh) data[ 'access' ] = str (refresh.access_token) data[ 'username' ] = self .user.username return data |
在 'users/views.py` 及 `simple/urls.py` 中编写如下代码:
# users/views.py from rest_framework_simplejwt.views import TokenObtainPairView from users.serializers import MyTokenObtainPairSerializer class MyTokenObtainPairView(TokenObtainPairView): serializer_class = MyTokenObtainPairSerializer # simple/urls.py from users.views import MyTokenObtainPairView urlpatterns = [ ... # modify path( 'login/' , MyTokenObtainPairView.as_view(), name = 'token_obtain_pair' ), ] |
测试 API,可以看到返回的信息中多了 username 信息:
http -f POST :8000/login/ username=admin password=123456
6. 手动颁发 token
手动颁发 token 主要针对用户注册的情况,用户注册完之后直接返回 token。
以下代码即针对一个 user 对象手动颁发一个 token 并返回。(用户注册同理,即 user 对象为注册后获取的用户)
# users/views.py class MyView(APIView): permission_classes = [permissions.IsAuthenticated] def get( self , request, * args, * * kwargs): return Response( "Get information successfully!" ) def post( self , request, * args, * * kwargs): refresh = RefreshToken.for_user(request.user) content = { 'refresh' : str (refresh), 'access' : str (refresh.access_token), } return Response(content) |