基于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
    评论
ruoyi是一个开源的Java框架,提供了一套快速开发管理系统的解决方案。在ruoyi框架中,可以使用JWT(JSON Web Token)进行身份认证JWT是一种规范,不与特定的编程语言绑定在一起。在ruoyi框架中,常用的Java实现是jjwt项目,它是一个开源项目,可以在GitHub上找到它的源代码。 要在ruoyi框架中使用JWT,首先需要在项目的pom.xml文件中添加JWT依赖项。可以通过添加如下代码来引入java-jwt依赖: ```xml <!-- jwt jar --> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.4.0</version> </dependency> ``` 接下来,可以通过在ruoyi框架中增加JWT登录方法来实现JWT认证。通常,可以使用一个名为JwtAuthenticationTokenFilter的认证过滤器来处理认证逻辑。 该过滤器继承自OncePerRequestFilter类,表示它只会过滤一次。在该过滤器中,可以实现JWT的验证逻辑,包括解析和验证JWT,获取用户信息等。 通过在ruoyi框架中实现JWT认证,可以实现基于JWT的身份认证和授权机制,提供更安全、可靠的权限管理功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [若依管理系统自学笔记二:JWT](https://blog.csdn.net/HDUCheater/article/details/119141978)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [若依集成jwt实现登录授权访问(单体版)](https://blog.csdn.net/qq_19309473/article/details/123650385)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值