首页 > 其他分享 >jwt自定义表签发, jwt 多方式登录(auth的user表)

jwt自定义表签发, jwt 多方式登录(auth的user表)

时间:2023-09-11 14:57:59浏览次数:43  
标签:username 自定义 jwt auth --- token user import

1 jwt自定义表签发

1.1 models.py

from django.db import models

from django.contrib.auth.models import AbstractUser


# 继承AbstractUser 直接使用自动签发token

# 纯自己写的用户表,需要自己签发
class User(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    email = models.EmailField(max_length=32)
    gender = models.IntegerField(choices=((1, '男'), (2, '女'), (0, '未知')))

1.2 视图

from django.shortcuts import render

from rest_framework.views import APIView
from .models import User
from rest_framework.response import Response

from rest_framework_jwt.settings import api_settings  # drf的配置文件

# from rest_framework_jwt.utils import jwt_payload_handler
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
# rest_framework_jwt.utils.jwt_encode_handler
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER


class UserView(APIView):
    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        user = User.objects.filter(username=username, password=password).first()
        if user:
            # 签发token
            # 1 通过user生成payload---》jwt 提供一个方法(username),传入user,返回payload
            # payload = jwt_payload_handler(user)
            payload={'username':'asdfasdf','exp':1694401763}
            # 2 生成token---》jwt提供了方法,把payload放入--》token
            token = jwt_encode_handler(payload)
            return Response({'code': 101, 'msg': '登录成功', 'token': token, 'username': user.username})
        else:
            return Response({'code': 101, 'msg': '用户名或密码错误'})

1.3 路由

path('login/', UserView.as_view()),

2 jwt 多方式登录(auth的user表)

#1 用户名+密码   邮箱+密码  手机号+密码  都可以登录
	username+password
    email+password
    phone+password
    
    无论是username,email,phone都以 username形式提交到后端
    于是:从username字段中取出来的,可能是用户名,可能是邮箱,可能是密码---》都能登录成功
#2  auth的user签发
#3  签发,校验用户 逻辑-----》放在序列化类中


# 5 存在一个问题---》已经迁移过表了---》已经存在auth的user表了,如果再去继承AbstractUser,再写用户表,就会出错
	-解决方案:以后尽量不要这么做
    	-以后要扩写auth的user表,一开始就要扩写,不要等迁移完之后再扩写
    -删库
    -删迁移文件(不要删__init__.py和migrations文件夹)
    	-项目app的迁移文件
        -django内置app的admin和auth的迁移文件
    
    -重新迁移--两条命令
    -扩写auth的user表,需要在配置文件配置 ###重要
    
    
# 6 创建超级用户--->创建到扩写的表  auth的user--》AuthUser
	python  manage.py createsuperuser
    
    
    

2.1 总结流程

# 序列化,反序列化,数据校验---》只用来做数据校验
# 前端传过来的字段,都要,而且要校验 :username  password
# 只要视图类中执行 ser.is_valid():
	会走字段自己的规则---》username过不了---》因为有unique---》所有需要重写
    会走局部钩子---》咱们没写
    会走全局钩子---》全局钩子里校验
    	-分成了两个方法:好处是以后修改方法
        -_get_user :多方式的 ,以后改成单方式登录,只要该这个方法即可 
        -_get_token:用的第三方签发,后期改成自己的签发,只需要改它即可
        
  	-把生成的token和用户名放到了,序列化类中,单是怕污染数据,放到了序列化类的对象的context中
    
# 视图类中取出来
	 token = ser.context.get('token')
     username = ser.context.get('username')

2.2 序列化类

from .models import AuthUser
from rest_framework import serializers
import re
from rest_framework.exceptions import ValidationError
from rest_framework_jwt.settings import api_settings  # drf的配置文件

# from rest_framework_jwt.utils import jwt_payload_handler
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
# rest_framework_jwt.utils.jwt_encode_handler
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER


# 序列化类干什么? 只用来反序列化的校验
class LoginSerializer(serializers.ModelSerializer):
    # username 是表中的字段---》自动映射过来的-->A user with that username already exists
    # username有字段自己的规则---》唯一 unique---》去数据库查询发现有lqz,之间字段自己规则报错了,不会走到全局钩子
    username=serializers.CharField() # 需要重写字段,不重写,字段自己规则过不了
    class Meta:
        model = AuthUser  # 千万不要加逗号,程序运行不会报错,使用这个地方的时候,就报错了
        fields = ['username', 'password']


    # 在类内部  用 __ 开头表示隐藏
    # 我们约定俗称,以 _ 开头的,表示只在类内部使用,不给外部用,但是万一外部要用,之间用既可以了
    def _get_user(self, attrs):
        # 用户名从哪拿? attrs是前端传入,校验过后的数据  {"username": "lqz","password": "lqz12345" }
        username = attrs.get('username')
        password = attrs.get('password')
        if re.match(r'^1[3-9][0-9]{9}$', username):  # 说明,用户提交的是手机号+密码
            user = AuthUser.objects.filter(phone=username).first()
        elif re.match(r'^.+@.+$', username):  # (这个邮箱正则,不太准确) 如果是邮箱,说明用户提交的是  邮箱+密码
            user = AuthUser.objects.filter(email=username).first()
        else:
            user = AuthUser.objects.filter(username=username).first()

        if user and user.check_password(password):
            return user
        else:
            # 在全局钩子中,只要校验不通过,就抛异常
            # 不是return
            raise ValidationError('用户名或密码错误')

    def _get_token(self, user):
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        return token

    def validate(self, attrs):
        # 1 校验用户

        user = self._get_user(attrs)  # 如果返回user,说明,用户名密码对了,如果没走到这里,说明抛异常,抛异常说明用户名密码错误

        # 2签发token
        token = self._get_token(user)

        # 3 放在这里面  self 是序列化类的对象  ,context 是空字典,它是  视图类和序列化类之间沟通的桥梁
        self.context['token'] = token
        self.context['username'] = user.username

        # 4 返回校验过后的数据
        return attrs

2.3 视图类

from rest_framework_jwt.views import obtain_jwt_token
## 复杂方式---》校验逻辑--》放在序列化类中
class UserView(GenericViewSet):
    # queryset = 可以不写
    serializer_class = LoginSerializer

    @action(methods=['POST'], detail=False)
    def login(self, request, *args, **kwargs):
        # 拿到前端传入的用户名和密码,得到一个序列化类对象
        ser = self.get_serializer(data=request.data)

        if ser.is_valid():  # 字段自己(校验不过,因为username在数据库中有你传入的这个名字了),局部钩子,全局钩子---》需要在序列化类中写
            # 校验完,并且签发完token了
            # token从 序列化类的对象 取出来
            # username从   序列化类的对象 取出来
            # 现在不明白如何取出来的,假设取出来是对的---》因为在全局钩子中放入到了context中
            token = ser.context.get('token')
            username = ser.context.get('username')

            return Response({'code': 100, 'msg': '登录成功', 'token': token, 'username': username})
        else:
            return Response({'code': 101, 'msg':'用户名密码错误'})

2.4 路由

from django.contrib import admin
from django.urls import path
from app01.views import UserView
from rest_framework.routers import SimpleRouter

router = SimpleRouter()
router.register('user', UserView, 'user') # 127.0.0.1:8000/user/login  的post请求
urlpatterns = [
    path('admin/', admin.site.urls),
    # path('login/', UserView.as_view()),
]
urlpatterns += router.urls

标签:username,自定义,jwt,auth,---,token,user,import
From: https://www.cnblogs.com/huangchunfang/p/17693540.html

相关文章

  • Vue2x的自定义指令
    在某些情况下,我们需要对底层DOM进行操作,而内置的指令不能满足需求,就需要自定义指令。一个自定义指令由一个包含类似组件的生命周期的钩子的对象来定义,钩子函数会接收到指令所绑定的元素作为参数。定义指令常用两种方式进行自定义指令,一种是全局定义,另一种在当前组件中定义//局......
  • SpringBoot + 自定义注解,实现用户操作日志(支持SpEL表达式)
    背景一个成熟的系统,都会针对一些关键的操作,去创建用户操作日志。比如:XX人创建了一条订单,订单号:XXXXXXXXX因为操作人或者订单号是动态的,所以有些开发人员,不知道获取,就将这种操作日志和业务代码融在一起。我们当然要杜绝这种现象,一定会有更好的解决方案。当前项目除了......
  • MySQL数据库进阶 自定义函数
    自定义函数在MySQL中,您可以使用自定义函数来扩展数据库管理系统的功能。自定义函数允许您封装一段可重用的代码,并在查询和其他操作中调用它。以下是在MySQL中创建和使用自定义函数的一般步骤:1、创建自定义函数语法:CREATEFUNCTIONfunction_name(parameters)RETURNSreturn_t......
  • drf - 过滤、排序、异常源码剖析、jwt
    过滤类的源码剖析1、为什么在视图类中配置了一个过滤类,就可以走? -filter_backends=[SearchFilter,MyFilter]2、前提条件是必须继承在视图类中继承GenericAPIView: 因为filter_backends是GenericAPIView的类属性。3、如果光继承了GenericAPIView还是不行,还需要再继承List......
  • 登录拦截器校验JWT
    importcom.alibaba.csp.sentinel.util.StringUtil;importcom.xtw.enums.BizCodeEnum;importcom.xtw.model.LoginUser;importcom.xtw.util.CommonUtil;importcom.xtw.util.JWTUtil;importcom.xtw.util.JsonData;importio.jsonwebtoken.Claims;importorg.springf......
  • jeecgboot 自定义导出字段
    实体类@DatapublicclassCostimplementsSerializable{/**主键*/@ApiModelProperty(value="主键")privateStringid;/**日期*/@Excel(name="日期",format="yyyy-MM-dd")@JsonFormat(timezone="GMT+8......
  • idea自定义TODO接口
    设置搜索TODO取消默认勾选的颜色选择自定义的颜色......
  • 接口文档、jwt介绍和构成、jwt签发和认证、base64编码、drf-jwt编码、drf-jwt使用
    接口文档作为后端,接口写好了,需要编写接口文档作为前端,需要使用后端写的接口(移动端、web桌面端),可以照着接口文档写接口文档的展现形式:1.word、md,写好传到公司的某个平台===》前端可以下载使用2.自动生成接口文档===》后端通过配置===》把所写的接口都自动生成===》......
  • JWT
    1.介绍Jsonwebtoken(JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源......
  • jwt介绍和构成
    一、jwt介绍和构成1、jwt:JsonWebToken:web方向的token认证方案#做会话保持的发展历史 -https://www.cnblogs.com/liuqingzheng/p/8990027.html#jwt:JsonWebToken:web方向的token认证方案#在用户注册或登录后,我们想记录用户的登录状态,或者为用户创建身份认证的凭证(token......