首页 > 其他分享 >多方式登录

多方式登录

时间:2024-04-19 19:47:05浏览次数:19  
标签:username 登录 方式 get self access token user

路由

# 127.0.0.1:8000/app01/api/v1/jwt/login/--->post请求
router.register('jwt', UserJWTView, 'jwt')
urlpatterns = [
    # # 方案一: 前面可以再加前缀
    path('api/v1/', include(router.urls)),
    path('users/', UserView.as_view()),
    path('login/', token_obtain_pair), 
]

视图类

from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action
from .serializer import LoginJWTSerializer
class UserJWTView(GenericViewSet):
    serializer_class = LoginJWTSerializer
    @action(methods=['POST'],detail=False)
    def login(self,request,*args,**kwargs):
        # 正常逻辑:取出手机号/用户名/邮箱+密码--》去数据校验--》校验通过-->签发token--》返回给前端
        # 高级逻辑:使用序列化类做上述逻辑
        serializer=self.get_serializer(data=request.data)
        if serializer.is_valid(): # 执行 三层认证
            # 校验通过:会把user,access和refresh都放到序列化类对象中--》返回给前端、
            # 现在在视图类中----》有个序列化类--》把视图类中变量给序列化类---》序列化类的变量给视图类--》借助于context给[字典]
            refresh = serializer.context.get('refresh')
            access = serializer.context.get('access')
            return Response({'code': 100, 'msg': '登录成功', 'refresh': refresh, 'access': access})
        else:
            return Response({'code': 101, 'msg': serializer.errors})

序列化类

from rest_framework import serializers
import re
from .models import UserInfo
from rest_framework.exceptions import ValidationError
class LoginJWTSerializer(serializers.Serializer):
    username = serializers.CharField() # 可能是 用户名  手机号  邮箱
    password=serializers.CharField()
    def _get_user(self,attrs):
        # 1 校验用户
        username = attrs.get('username')
        password = attrs.get('password')
        # 2 去数据库 查询用户---》username可能是手机号,邮箱,用户名--》查的字段不一样
        # 2.1 正则匹配,是不是手机号
        if re.match(r'^1[3-9][0-9]{9}$', username):
            user = UserInfo.objects.filter(mobile=username).first()
        elif re.match('^.+@.+$', username):
            user = UserInfo.objects.filter(email=username).first()
        else:
            user = UserInfo.objects.filter(username=username).first()

        if user and user.check_password(password):
            return user
        else:
            raise ValidationError('用户名或密码错误')
    def validate(self, attrs):
        # 取出 手机号/用户名/邮箱+密码--》数据库校验--》校验通过签发 access和refresh,放到context中
        user=self._get_user(attrs)
        # 签发token--》通过user对象,签发token
        token = RefreshToken.for_user(user)
        self.context['access'] = str(token.access_token)
        self.context['refresh'] = str(token)
        return attrs  # 不返回不行:因为源码中校验了是否为空--》

总结

# 1 校验数据,放到序列化类的 validate中,而不放在视图类的方法中乐
# 2 视图类和序列化类直接交互变量
	serializer.context
    
# 3 user.check_password  必须是auth的user表,校验密码使用它


# 4 attrs必须返回值,返回空报错

# 5 视图类的方法校验失败的else中:也要return Response
# 6 如何签发token
token = RefreshToken.for_user(user)
self.context['access'] = str(token.access_token)
self.context['refresh'] = str(token)

2自定义用户表

签发roken

不扩写auth
只要重写def _get_user的逻辑就可以了

2.1 新建用户表

class User(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    user_type=models.IntegerField(choices=((1,'注册用户'),(2,'普通管理员'),(3,'超级管理员')),default=1)
    @property
    def is_authenticated(self):
        return True

2.2 登陆签发

2.2.1 路由

# 127.0.0.1:8000/app01/api/v1/our_jwt/login/--->post请求
router.register('our_jwt', UserOurJWTView, 'our_jwt')
# 127.0.0.1:8000/app01/api/v1/publish/--->get
router.register('publish', PublishView, 'publish')

2.2.2 视图类

class UserOurJWTView(GenericViewSet):
    serializer_class = LoginOurJWTSerializer
    @action(methods=['POST'],detail=False)
    def login(self,request,*args,**kwargs):
        serializer=self.get_serializer(data=request.data)
        if serializer.is_valid():
            refresh = serializer.context.get('refresh')
            access = serializer.context.get('access')
            return Response({'code': 100, 'msg': '登录成功', 'refresh': refresh, 'access': access})
        else:
            return Response({'code': 101, 'msg': serializer.errors})
        

2.2.3 序列化类

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.tokens import RefreshToken
from .models import User
class LoginOurJWTSerializer(serializers.Serializer):
    username = serializers.CharField() # 可能是 用户名  手机号  邮箱
    password=serializers.CharField()
    def _get_user(self,attrs):
        # 1 校验用户
        username = attrs.get('username')
        password = attrs.get('password')
        user=User.objects.filter(username=username,password=password).first()

        if user:
            return user
        else:
            raise ValidationError('用户名或密码错误')
    def validate(self, attrs):
        user=self._get_user(attrs)
        token = RefreshToken.for_user(user)
        self.context['access'] = str(token.access_token)
        self.context['refresh'] = str(token)
        return attrs

2.3 认证类

2.3.1 认证类

from rest_framework_simplejwt.authentication import JWTAuthentication
from .models import User
class JWTOurAuth(JWTAuthentication):
    def authenticate(self, request):
        # 取出用户携带的access---》放请求头中:Authorization
        token = request.META.get('HTTP_AUTHORIZATION')
        if token:
            # 校验token--》validated_token 返回的就是可以信任的payload
            validated_token = self.get_validated_token(token)
            user_id = validated_token['user_id']
            user = User.objects.filter(pk=user_id).first()
            return user, token
        else:
            raise AuthenticationFailed('请携带登录信息')

2.3.2 使用

# 登陆后才能访问
from .authentication import JWTOurAuth
class PublishView(GenericViewSet):
    authentication_classes = [JWTOurAuth]
    def list(self,request):
        return Response('get')

标签:username,登录,方式,get,self,access,token,user
From: https://www.cnblogs.com/dreammooncy/p/18145930

相关文章

  • React 简单登录平台Demo(2):使用Anti写登录框架
    目录前言参考登录页面基础框架layout.tsxpage.tsxTailWind使用好看的渐变颜色flex布局填充布局居中布局显示效果总结前言在适用了一下Anti之后发现,学起来成本实在太高了,先用Anti默认的目标凑合一下好了。反正我也就是一个普通的后端,能用React写就不错了,样式凑合凑合能用就行。......
  • Ubuntu 命令行工具使用代理的三种方式
    终端默认是不走代理的,即使我们已经打开了网络代理客户端的“全局代理”。用curl或wget下载GitHub上的文件时出现的443错误就是没有挂代理导致的。使用环境变量(推荐)很多Linux和Unix命令行工具(比如curl,wget,lynx等)使用名为http_proxy,https_proxy,ftp_proxy的环......
  • MySQL安全登录策略
    原文链接:https://blog.csdn.net/weixin_46106069/article/details/129183418今天看到了安装validate_password插件,查下是什么,学习下。MySQL密码复杂度策略设置:MySQL系统自带有validate_password插件,此插件可以验证密码强度,未达到规定强度的密码则不允许被设置。MySQL5.7......
  • 如何快速启动KVM虚拟机并用自定义用户登录
    以ubuntu虚拟机为例,很多时候创建了KVM虚拟机之后,想ssh登录进去做一些操作,但是却不知道用户名和密码,最早的时候ubuntu的cloudimage内置了一个cirros的用户名,密码也是cirros,现在好像没有这个用户了,所以想ssh虚拟机的话,可以借助cloudinit来在启动时创建一个指定的用户。以下以u......
  • windows11 配置账户登录锁定策略
    原文链接:https://blog.csdn.net/weixin_46119529/article/details/134162164一、打开本地策略有两种方法,都可以!!1、搜索“组策略”,或者 2、Win键+R输入“secpol.msc” 二、打开配置界面1、如果是搜索“组策略”,按以下步骤:      2、如果是Win键+R输入“sec......
  • sqlnet现在ip地址登录
    由于业务需要,需要使用白名单限制用户登录数据库的地址,决定使用数据库白名单功能一般单实例数据库启动白名单只需要在sqlnet.ora中添加以下内容即可:TCP.VALIDNODE_CHECKING=yes(开启IP限制功能),TCP.INVITED_NODES=(192.168.1.103,ip2,ip3,..,..本地IP..)--白名单,必须本地IP,否......
  • React 简单登录平台Demo(1):Next.js配置
    目录前言体验Next.js中文文档路径问题创建项目启动报错测试TailWindCSS热重载如何添加路由第三方库引入tailwindcss配置相关链接布局新建布局布局也是嵌套影响的根节点layout配置路由跳转Link跳转Hook跳转简单的登录页面前言我之前的那个项目写到后面,发现还不如直接用Next.js呢......
  • JavaScript本地存储的方式有哪些
    Web存储技术1.localStorage特点:长期存储,除非手动删除否则会一直保存在浏览器中,清除缓存或卸载浏览器后消失。存储语法:window.localStorage.setItem(名字,值)获取语法:window.localStorage.getItem(名字)删除语法:window.localStorage.removeItem(名字)作用:删除localStorage......
  • 根据微信code获取换取用户登录态信息
    1.根据微信code获取换取用户登录态信息点击查看代码/***根据code获取小程序用户openpid*/@OverridepublicR<Map<String,String>>getUnitCheckPersonOpenId(Stringcode){R<Map<String,String>>resMap=newR<>();//获取......
  • 小程序生态是更灵活构建超级App的方式
    互联网从1.0发展至今,已经经历了几十年的进步和变迁,催生出很多垂直领域的超级App。以下就是几个典型的超级App:1、电子商务Shopee(新加坡):东南亚最大的电子商务平台,拥有超过3.6亿活跃用户,覆盖7个国家和地区。Shopee提供广泛的商品品类,包括服饰、电子产品、家居用品等,并提供多种......