栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

基于Django的JWT 实现(rest

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

基于Django的JWT 实现(rest

实现方式
  • rest_framework_simplejwt 库实现
  • 复用Django自带的用户表
官网
  • 最新版的django(4x系列)无法在使用jwt,
  • 其开发者推荐的替代品为Simple JWT(djangorestframework-simplejwt)
  • https://github.com/jpadilla/django-rest-framework-jwt

Django JWT实践
# 安装依赖
# pip install djangorestframework-jwt

##
pip install djangorestframework-simplejwt
打开项目中settings配置
## 
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'users'
]

## 全局配置
REST_FRAMEWORK = {
   # 设置所有接口都需要被验证
  'DEFAULT_PERMISSION_CLASSES': (
      # 设置所有接口都需要被验证
       'rest_framework.permissions.IsAuthenticated',  # 默认权限为验证用户
  ),
    # 用户登录的认证方式
  'DEFAULT_AUTHENTICATION_CLASSES': (
      'rest_framework_simplejwt.authentication.JWTAuthentication'   # 使用rest_framework_simplejwt验证身份
  )
}

## 设置token的有效时长
SIMPLE_JWT={
    # token有效时长
    'ACCESS_TOKEN_LIFETIME': datetime.timedelta(minutes=10),
    # token刷新后的有效时间
    'REFRESH_TOKEN_LIFETIME': datetime.timedelta(days=1),
}
  • AllowAny 允许所有用户
  • IsAuthenticated 仅通过认证的用户
  • IsAdminUser 仅管理员用户
  • IsAuthenticatedOrReadOnly 认证的用户可以完全操作,否则只能get读取
创建用户表
# 创建用户应用
python manage.py startapp users
配置路由
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 rest_framework_simplejwt.views import (TokenObtainPairView, TokenRefreshView)
from users import views

urlpatterns = [
    path(r'token/obtain', TokenObtainPairView.as_view(), name="obtain_token"),
    path(r'detail',views.DetailsView.as_view(),name="detail")
]
编写序列化器

vim serializers.py

from django.contrib.auth import get_user_model
from rest_framework import serializers
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
import time

# 如果自定义了用户表,那么就要使用这个方法来获取用户模型
# 没有自定义的话可以使用以下方式加载用户模型:
from django.contrib.auth.models import User

# 不过这种是万能的
# User = get_user_model()


# 重写TokenObtainPairSerializer类的部分方法以实现自定义数据响应结构和payload内容
class MyTokenSerializer(TokenObtainPairSerializer):

    @classmethod
    def get_token(cls, user):
        """
        此方法往token的有效负载 payload 里面添加数据
        例如自定义了用户表结构,可以在这里面添加用户邮箱,头像图片地址,性别,年龄等可以公开的信息
        这部分放在token里面是可以被解析的,所以不要放比较私密的信息

        :param user: 用戶信息
        :return: token
        """
        token = super().get_token(user)
        # 添加个人信息
        token['name'] = user.username
        return token

    def validate(self, attrs):
        """
        此方法为响应数据结构处理
        原有的响应数据结构无法满足需求,在这里重写结构如下:
        {
            "refresh": "xxxx.xxxxx.xxxxx",
            "access": "xxxx.xxxx.xxxx",
            "expire": Token有效期截止时间,
            "username": "用户名",
        }
        :param attrs: 請求參數
        :return: 响应数据
        """
        # data是个字典
        # 其结构为:{'refresh': '用于刷新token的令牌', 'access': '用于身份验证的Token值'}
        data = super().validate(attrs)

        # 获取Token对象
        refresh = self.get_token(self.user)
        #加个token的键,值和access键一样
        data['token']=data['access']
        #然后把access键干掉
        del data['access']
        # 令牌到期时间
        timestamp = refresh.access_token.payload['exp']  # 有效期-时间戳
        time_local = time.localtime(int(timestamp))
        data['expire'] = time.strftime("%Y-%m-%d %H:%M:%S", time_local)

        # 用户名
        data['username'] = self.user.username

        return data
编写视图类
from django.http import  HttpResponse,JsonResponse
from rest_framework.views import APIView
from rest_framework.views import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework_simplejwt import authentication
from rest_framework_simplejwt.views import TokenViewBase
from rest_framework import status
from rest_framework import permissions
##
from .serializers import MyTokenSerializer

# Create your views here.

##  不需要携带token就能访问接口
def ListShops(requests):
    return HttpResponse("this is shop list")


class DetailsView(APIView):
    permission_classes = [permissions.IsAuthenticated]
    authentication_classes = (authentication.JWTAuthentication,)

    def get(self, request, *args, **kwargs):
        print('authenticate: ', request.successful_authenticator.authenticate(request))
        print('token信息: ', request.successful_authenticator.get_validated_token(
            request.successful_authenticator.get_raw_token(request.successful_authenticator.get_header(request))))
        print('登录用户: ', request.successful_authenticator.get_user(request.successful_authenticator.get_validated_token(
            request.successful_authenticator.get_raw_token(request.successful_authenticator.get_header(request)))))
        return Response('get ok')

    def post(self, request, *args, **kwargs):
        return Response('post ok')


# 自定义的登陆视图
class LoginView(TokenViewBase):
    serializer_class = MyTokenSerializer  # 使用刚刚编写的序列化类

    # post方法对应post请求,登陆时post请求在这里处理
    def post(self, request, *args, **kwargs):
        # 使用刚刚编写时序列化处理登陆验证及数据响应
        serializer = self.get_serializer(data=request.data)
        try:
            serializer.is_valid(raise_exception=True)
        except Exception as e:
            raise ValueError(f'验证失败: {e}')

        return Response(serializer.validated_data, status=status.HTTP_200_OK)


创建表结构
## 
D:py-resdevops>python manage.py migrate

##
python manage.py createsuperuser

#  添加用户
http://127.0.0.1:8001/admin/auth/user/
测试

 

通过 Token 获取视图信息:

 控制台信息:

System check identified no issues (0 silenced).
June 01, 2022 - 15:36:51
Django version 3.2, using settings 'devops.settings'
Starting development server at http://0.0.0.0:8001/
Quit the server with CTRL-BREAK.
Unauthorized: /users/detail
[01/Jun/2022 15:36:55] "GET /users/detail HTTP/1.1" 401 183
Unauthorized: /users/detail
[01/Jun/2022 15:37:02] "GET /users/detail HTTP/1.1" 401 183
Bad Request: /users/token/obtain
[01/Jun/2022 15:37:10] "POST /users/token/obtain HTTP/1.1" 400 12791
[01/Jun/2022 15:37:15] "POST /users/token/obtain HTTP/1.1" 200 12954
authenticate:  (, {'token_type': 'access', 'exp': 1654069335, 'iat': 1654069035, 'jti': '2b7b1e19bbbc44749115e68f630ab968', 'user_id': 1})
token信息:  eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjU0MDY5MzM1LCJpYXQiOjE2NTQwNjkwMzUsImp0aSI6IjJiN2IxZTE5YmJiYzQ0NzQ5MTE1ZTY4ZjYzMGFiOTY4IiwidXNlcl9pZCI6MX0.UkKXBDxES849wj2d3CiOipDUm6s_C-LLIf1tlRnxkmI
登录用户:  knight
[01/Jun/2022 15:37:27] "GET /users/detail HTTP/1.1" 200 8

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/942902.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号