背景
由于jwt默认使用django自带的User表,若使用自定义User表需要改造获取token的视图,继承官方文档提供的视图 TokenObtainPairSerializer,TokenObtainPairView
自带用户表的实现参考: 基于Django的JWT 实现(rest_framework_simplejwt 库)_叱咤少帅(少帅)的博客-CSDN博客
settings.py 配置
INSTALLED_APPS = [
....
'rest_framework',
'mall',
'users'
]
## 全局配置
REST_FRAMEWORK = {
# 设置所有接口都需要被验证
'DEFAULT_PERMISSION_CLASSES': (
# 设置所有接口都需要被验证
'rest_framework.permissions.IsAuthenticated', # 默认权限为验证用户
),
}
## 设置token的有效时长
SIMPLE_JWT={
# token有效时长
'ACCESS_TOKEN_LIFETIME': datetime.timedelta(minutes=10),
# token刷新后的有效时间
'REFRESH_TOKEN_LIFETIME': datetime.timedelta(days=1),
}
devops/urls.py 配置
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
# 用户模块
path("users/",include('users.urls')),
# 商场模块路径
path("mall/",include('mall.urls')),
]
users/urls.py配置
from django.urls import path
from users.auth import MyTokenObtainPairView
from users.views import ListView
# jwt内部实现的登陆视图
from rest_framework_simplejwt.views import (TokenObtainPairView, TokenRefreshView)
urlpatterns =[
path(r'lg', TokenObtainPairView.as_view(), name="obtain_token"),
path(r'login', MyTokenObtainPairView.as_view(),name="login"), # 自定义用户表返回token
path(r'list',ListView.as_view(),name="list"),
]
users/auth.py配置
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework_simplejwt.exceptions import InvalidToken, AuthenticationFailed
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework import exceptions
import time
from django.utils.translation import gettext_lazy as _
from users.models import User
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
"""
自定义登录认证,使用自有用户表
"""
username_field = 'username'
def validate(self, attrs):
authenticate_kwargs = {self.username_field: attrs[self.username_field], 'password': attrs['password']}
print(authenticate_kwargs)
try:
user = User.objects.get(**authenticate_kwargs)
except Exception as e:
raise exceptions.NotFound(e.args[0])
refresh = self.get_token(user)
# token的 过期时间
timestamp = refresh.access_token.payload['exp'] # 有效期-时间戳
time_local = time.localtime(int(timestamp))
expire_time = time.strftime("%Y-%m-%d %H:%M:%S", time_local)
data = {"userId": user.id,"username":user.username,"token": str(refresh.access_token), "refresh": str(refresh),"expire":expire_time}
return data
class MyTokenObtainPairView(TokenObtainPairView):
serializer_class = MyTokenObtainPairSerializer
class MyJWTAuthentication(JWTAuthentication):
'''
修改JWT认证类,返回自定义User表对象
'''
def get_user(self, validated_token):
try:
user_id = validated_token['user_id']
except KeyError:
raise InvalidToken(_('Token contained no recognizable user identification'))
try:
user = User.objects.get(**{
'id': user_id})
except User.DoesNotExist:
raise AuthenticationFailed(_('User not found'), code='user_not_found')
return user
users/views.py 配置
from django.http import HttpResponse,JsonResponse
from rest_framework.views import Response
from rest_framework.views import APIView
from rest_framework import permissions
from rest_framework_simplejwt import authentication
# Create your views here.
## 不需要携带token就能访问接口
def ListShops(requests):
return HttpResponse("this is shop list")
# 需要携带token才可以访问的视图
class ListView(APIView):
# 需要token才可以访问的视图
permission_classes = [permissions.IsAuthenticated]
authentication_classes = (authentication.JWTAuthentication,)
def get(self, request, *args, **kwargs):
return Response('Get OK')
def post(self, request, *args, **kwargs):
return Response('Post OK')