基于JWT认证的多登录方式

第一种 基于视图类编写逻辑

# 视图类
class UserView(APIView):
	# 局部禁用
    authentication_classes = ()
    permission_classes = ()

    def post(self, request):
        # 1  request取出用户名和密码
        username = request.data.get('username')
        password = request.data.get('password')
        print(username)
        # 2  使用正则判断用用户名是邮箱,手机号还是用户名,分别去查询当前用户
        if re.match(r'^1[3-9][0-9]{9}$', username):
            user = User.objects.filter(mobile=username).first()
        elif re.match(r'^.+@.+$', username):
            user = User.objects.filter(email=username).first()
        else:
            user = User.objects.filter(username=username).first()
        if user and user.check_password(password):
            # 3 校验密码
            # 4 签发token
            refresh = TokenObtainPairSerializer.get_token(user)
            # 5 返回给前端
            return Response({'code': 100, 'msg': '成功', 'access': str(refresh.access_token), 'refresh': str(refresh)})
        else:
            return Response({'code': 101, 'msg': '用户名或密码错误'})


# serizlizer 序列化类

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    # 往荷载中加东西
    @classmethod
    def get_token(cls, user):  # user就是登录成功,查到的用户
        token = super().get_token(user)  # 签发token
        token['name'] = user.username  # 往荷载中加用户名
        return token
	# 校验数据通过之后才返回给 前端
    def validate(self, attrs):
        #
        old_data = super().validate(attrs)
        data = {'code': 100,
                'msg': '登录成功成功',
                'username': self.user.username,
                'refresh': old_data['refresh'],
                'access': old_data['access']
                }
        return data

# 路由:
from rest_framework_simplejwt.views import token_obtain_pair, token_verify, token_refresh

urlpatterns = [
    path('admin/', admin.site.urls),
    
    path('login/', token_obtain_pair),
    path('verify/', token_verify),
    path('refresh/', token_refresh),

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

]

第二种 逻辑处理在序列化类中

# 视图类
from rest_framework.generics import GenericAPIView
from .serializer import LoginSerializer

class LoginView(GenericAPIView):
    authentication_classes = ()
    permission_classes = ()
    serializer_class = LoginSerializer

    def post(self, request):
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():  # 会执行字段自己的校验(没有),执行局部钩子(没有),执行全局钩子(写了:校验用户,签发token)
            # context 是视图类和序列化列之间沟通的桥梁
            access = ser.context.get('access')
            refresh = ser.context.get('refresh')
            username = ser.context.get('username')
            return Response({'code': 100, 'msg': '成功', 'username': username, 'access': access, 'refresh': refresh})
        else:
            return Response({'code': 101, 'msg': '用户名或密码错误'})


# 序列化类
from rest_framework import serializers
from .models import User
import re
from rest_framework.exceptions import ValidationError

class LoginSerializer(serializers.Serializer):
    username = serializers.CharField()
    password = serializers.CharField()

    # 写全局钩子
    def validate(self, attrs):
        # 校验用户,签发token
        username = attrs.get('username')
        password = attrs.get('password')
        # 2  使用正则判断用用户名是邮箱,手机号还是用户名,分别去查询当前用户
        if re.match(r'^1[3-9][0-9]{9}$', username):
            user = User.objects.filter(mobile=username).first()
        elif re.match(r'^.+@.+$', username):
            user = User.objects.filter(email=username).first()
        else:
            user = User.objects.filter(username=username).first()
        if user and user.check_password(password):
            # 3 校验密码
            # 4 签发token 校验通过之后 把token串放在 context 中 视图类取的时候在  if ser.is_valid() 中取ser.context中取
            refresh = TokenObtainPairSerializer.get_token(user) # user 是当前登录用户

            self.context['access'] = str(refresh.access_token)
            self.context['refresh'] = str(refresh)
            self.context['username'] = user.username
            return attrs
        else:
            raise ValidationError('用户名或密码错误')

第三种方式

# 视图类
from rest_framework.generics import GenericAPIView
from .serializer import LoginSerializers

class Userview(GenericAPIView):

    authentication_classes = ()
    permission_classes = ()
    serializer_class = LoginSerializers

    def post(self, request):
        ser = LoginSerializers(data=request.data)
        if ser.is_valid():  # 会执行字段自己的校验(没有),执行局部钩子(没有),执行全局钩子(写了:校验用户,签发token)

            # ser.validated_data # 字典,校验过后的数据 可以直接在ser对象中取
            return Response(ser.validated_data)
        else:
            return Response({'code': 101, 'msg': '用户名或密码错误11'})

# 序列化类
class LoginSerializers(serializers.Serializer):

    username = serializers.CharField()
    password = serializers.CharField()

    # 写全局钩子
    def validate(self, attrs):
        # 校验用户,签发token
        username = attrs.get('username')
        password = attrs.get('password')
        # 2  使用正则判断用用户名是邮箱,手机号还是用户名,分别去查询当前用户
        if re.match(r'^1[3-9][0-9]{9}$', username):
            user = User.objects.filter(mobile=username).first()
        elif re.match(r'^.+@.+$', username):
            user = User.objects.filter(email=username).first()
        else:
            user = User.objects.filter(username=username).first()
        if user and user.check_password(password):
            # 3 校验密码
            # 4 签发token
            refresh = TokenObtainPairSerializer.get_token(user)
            data = {'code': 100,
                    'msg': '登录成功成功',
                    'username': user.username,  # 校验的用户就是当前用户
                    'refresh': str(refresh),  # 因为是对象 所以内部用了__str__ 方法转成了字符串
                    'access': str(refresh.access_token)
                    }
            return data
        else:
            raise ValidationError('用户名或密码错误')

第四种方式

# post 请求局部禁用 
# 其他请求全局禁用 需要登录之后带着token才能访问
# 视图类
class UserView(APIView):

    def post(self, request):
        # 1  request取出用户名和密码
        if request.data:
            username = request.data.get('username')
            password = request.data.get('password')

            # 2  使用正则判断用用户名是邮箱,手机号还是用户名,分别去查询当前用户

            if re.match(r'^1[3-9][0-9]{9}$', username):
                user = User.objects.filter(mobile=username).first()
            elif re.match(r'^.+@.+$', username):
                user = User.objects.filter(email=username).first()
            else:
                user = User.objects.filter(username=username).first()
            if user and user.check_password(password):
                # 3 校验密码
                # 4 签发token
                refresh = TokenObtainPairSerializer.get_token(user)
                # 5 返回给前端
                return Response({'code': 100, 'msg': '成功', 'access': str(refresh.access_token), 'refresh': str(refresh)})
            else:
                return Response({'code': 101, 'msg': '用户名或密码错误'})
        else:
            return Response({'code': 101, 'msg': '用户名或密码不能为空'})

    def get(self, request):

        return Response('登录才能访问')

    def put(self,request):
        return Response('修改才能访问')
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request_action = None

    def initialize_request(self, request, *args, **kwargs):
        self.request_action = request.method.lower()
        return super().initialize_request(request, *args, **kwargs)

    def get_authenticators(self):
        if self.request_action == 'post':
            self.authentication_classes = []
        return super().get_authenticators()

    def get_permissions(self):
        if self.request_action == 'post':
            self.permission_classes = []
        return super().get_permissions()

# 序列化类
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer


class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    # 往荷载中加东西
    @classmethod
    def get_token(cls, user):  # user就是登录成功,查到的用户
        token = super().get_token(user)  # 签发token
        token['name'] = user.username  # 往荷载中加用户名
        return token

    def validate(self, attrs):
        #
        old_data = super().validate(attrs)
        data = {'code': 100,
                'msg': '登录成功成功',
                'username': self.user.username,
                'refresh': old_data['refresh'],
                'access': old_data['access']
                }
        return data

# 配置文件
AUTH_USER_MODEL = 'app01.User'
import datetime
SIMPLE_JWT = {
    "TOKEN_OBTAIN_SERIALIZER": "app01.serializer.MyTokenObtainPairSerializer",
    'ACCESS_TOKEN_LIFETIME': datetime.timedelta(minutes=30),
    # refresh的token有效时间,
    'REFRESH_TOKEN_LIFETIME': datetime.timedelta(days=1),
}
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ]
}


INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01',
    'rest_framework_simplejwt',
    'rest_framework'

]

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值