认证权限频率自定义签发token-多方式登录(代码片段)

setcreed setcreed     2023-04-30     621

关键词:

三大认证流程图

技术图片

路由配置

在应用下新建文件router.py

# router.py
from rest_framework.routers import Route, DynamicRoute, SimpleRouter as DRFSimpleRouter


class SimpleRouter(DRFSimpleRouter):
    routes = [
        # List route.
        Route(
            url=r'^prefixtrailing_slash$',
            mapping=
                'get': 'list',
                'post': 'create',
                'put': 'multiply_update',
                'patch': 'multiply_partial_update',
                'delete': 'multiply_destroy'
            ,
            name='basename-list',
            detail=False,
            initkwargs='suffix': 'List'
        ),
        # Dynamically generated list routes. Generated using
        # @action(detail=False) decorator on methods of the viewset.
        DynamicRoute(
            url=r'^prefix/url_pathtrailing_slash$',
            name='basename-url_name',
            detail=False,
            initkwargs=
        ),
        # Detail route.
        Route(
            url=r'^prefix/lookuptrailing_slash$',
            mapping=
                'get': 'retrieve',
                'put': 'update',
                'patch': 'partial_update',
                'delete': 'destroy'
            ,
            name='basename-detail',
            detail=True,
            initkwargs='suffix': 'Instance'
        ),
        # Dynamically generated detail routes. Generated using
        # @action(detail=True) decorator on methods of the viewset.
        DynamicRoute(
            url=r'^prefix/lookup/url_pathtrailing_slash$',
            name='basename-url_name',
            detail=True,
            initkwargs=
        ),
    ]


router = SimpleRouter()

urls.py

# urls.py

from django.conf.urls import url, include
from .router import router
from . import views
router.register('users', views.UserListAPIViewSet, basename='user')

urlpatterns = [
    url(r'', include(router.urls))
]

认证组件

配置drf-jwt框架的认证类 认证组件只能决定request.user,不是断定权限的地方,所以一般配置全局

# settings.py

REST_FRAMEWORK = 
    # 认证组件
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication'
    ],

新建文件authentications.py,自定义认证

from rest_framework.authentication import BaseAuthentication

# 自定义认证类
# 如果使用session认证,drf默认提供了SessionAuthentication
# 如果使用drf-jwt认证,drf-jwt默认提供了JSONWebTokenAuthentication
# 如果自定义签发与校验token,才需要将校验token的算法封装到自定义的认证类

from rest_framework_jwt.authentication import JSONWebTokenAuthentication
class MyAuthentication(BaseAuthentication):
    def authenticate(self, request):
        pass
        # 1、从请求头中拿到前台提交的token(一般从HTTP_AUTHORIZATION中拿,也可以与前台约定)
        #       如果设置了反爬
        # 2、没有token,返回None,代表游客
        # 3、有token,进入校验    不通过,抛异常,代表非法用户;通过,返回(user, token),代表合法用户

自定义认证规则:

  • 从请求头中拿到前台提交的token(一般从HTTP_AUTHORIZATION中拿,也可以与前台约定)

    • 如果设置了反爬等措施,校验一下反爬(头 token)
  • 没有token,返回None,代表游客
  • 有token,进入校验
    • 不通过,抛异常,代表非法用户
    • 通过,返回(user, token),代表合法用户

认证组件源码分析:

技术图片

技术图片

权限组件

权限类就是实现 BasePermission类,重写has_permission 方法,如果有权限返回True,没权限返回False。

局部配置权限:

# views.py

# 权限组件
permission_classes = [permissions.MyPermission]

自定义权限类

# permissions.py
from rest_framework.permissions import BasePermission

class MyPermission(BasePermission):
    def has_permission(self, request, view):
        """
        根据需求,request和view的辅助,制定权限规则判断条件
        如果条件通过,返回True
        如果条件不通过,返回False
        """
        pass

配置drf自带的权限类

  • drf默认提供了一些权限类
    • AllowAny:游客和登录用户全权限
    • IsAuthenticated:只有登录用户有全权限
    • IsAdminUser:只有后台用户(admin)有全权限
    • IsAuthenticatedOrReadOnly:游客有读权限,登录用户有全权限
  • 如果有特殊需要,需要自定义权限类
    • 如:只有superuser有权限、只有vip用户有权限、只有某ip网段用户有权限、只有某个视图及其子类有权限
# views.py
from rest_framework.viewsets import GenericViewSet
from rest_framework import mixins
from .response import APIResponse
from rest_framework.permissions import IsAuthenticated

class UserListAPIViewSet(mixins.ListModelMixin, GenericViewSet):
    permission_classes = [IsAuthenticated]
    pass

drf-jwt 签发token源码分析

"""
drf-jwt 签发token
1、username、password 通过auth组件的authenticate方法得到user对象
2、user对象、通过drf-jwt框架的jwt_payload_handler函数包装 payload载荷
3、payload载荷 通过drf-jwt框架的jwt_encode_handler函数签发 token字符串

注:可以借助jwt_payload_handler和jwt_encode_handler 两个函数完成自定义token的签发
"""

多方式登录 签发token

  • token只能 由在登录接口 签发

  • 登录接口也是APIView的子类,使用一定会进行 认证、权限、组件的校验

  • 结论:不管系统默认、或是全局settings配置的是何 认证与权限组件,登录接口不用参与任何认证与权限的校验。所以,登录接口一定要进行 认证与权限的局部禁用

from rest_framework.views import APIView


class LoginAPIView(APIView):
    authentication_classes = []
    permission_classes = []

    def post(self, request, *args, **kwargs):
        serializers = serializer.LoginModelSerializer(data=request.data)
        serializers.is_valid(raise_exception=True)  # 内部在全局钩子中完成token的签发
        return APIResponse(results=
            'username': '',
            'token': ''
        )

这样会有个问题:post方法默认走的是数据库的增方法

默认的校验规则里面是走的数据库,我们可以自定义字段

# 序列化类 serializer.py
from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
import re
class LoginModelSerializer(serializers.ModelSerializer):
    username = serializers.CharField(min_length=3, max_length=16)
    password = serializers.CharField(min_length=3, max_length=16)
    class Meta:
        model = models.User
        fields = ['username', 'password']

    # 用全局钩子,完成token的签发
    def validate(self, attrs):
        # 1、通过username、password完成多方式登录校验,得到user对象
        user = self._validate_user(attrs)
        # 2、user对象包装怕payload载荷
        payload = jwt_payload_handler(user)
        # 3、payload载荷签发token
        token = jwt_encode_handler(payload)
        # 4、将user与token存储到serializer对象中,方便在视图类中使用
        self.content = 
            'user': user,
            'token': token
        
        return attrs


    def _validate_user(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')

        if re.match(r'.*@.*', username):    # 邮箱
            user = models.User.objects.filter(email=username).first()
        elif re.match(r'^1[1-9][0-9]9$', username):  # 电话
            user = models.User.objects.filter(mobile=username).first()
        else:  # 用户名
            user = models.User.objects.filter(username=username).first()

        if not user or not user.check_password(password):
            raise serializers.ValidationError('message': '用户信息异常')

        return user
# views.py

from rest_framework.views import APIView


class LoginAPIView(APIView):
    authentication_classes = []
    permission_classes = []

    def post(self, request, *args, **kwargs):
        serializers = serializer.LoginModelSerializer(data=request.data)
        serializers.is_valid(raise_exception=True)  # 内部在全局钩子中完成token的签发
        print(serializers.content)
        return APIResponse(results=
            'username': serializers.content.get('user').username,
            'token': serializers.content.get('token')
        )

总结:认证与权限绑定使用

  • 每一个视图类都要进行认证,且认证规则一致,多余全局配置认证即可
  • 每一个视图类都要进行权限校验,默认配置的是 不限制(AllowAny),但实际开发中,视图类的访问权限不完全相同,所以要在具体的视图类,配置具体的权限规则

VIP用户认证权限例子

# views.py

from rest_framework.viewsets import ViewSet
class UserViewSet(ViewSet):
    # 权限:只要VIP用户可以查看 个人详细信息
    permission_classes = [permissions.VIPUserPermission]
    def retrieve(self, request, *args, **kwargs):
        return APIResponse(results=
            'username': request.user.username,
            'email': request.user.username,
            'mobile': request.user.username,
            'data_joined': request.user.date_joined,
        )
# permission.py
from rest_framework.permissions import BasePermission

# VIP用户权限
class VIPUserPermission(BasePermission):
    def has_permission(self, request, view):
        for group in request.user.groups.all():
            if group.name.lower() == 'vip':
                return True
        return False

频率组件

技术图片

技术图片

# views.py
class UserListAPIViewSet(mixins.ListModelMixin, GenericViewSet):
    from rest_framework.throttling import AnonRateThrottle, UserRateThrottle
    # 频率组件
    # throttle_classes = [AnonRateThrottle]
    throttle_classes = [UserRateThrottle]
    
    queryset = models.User.objects.filter(is_active=True).all()
    serializer_class = serializer.UserModelSerializer

    def update(self, request, *args, **kwargs):
        return APIResponse()

    def multiply_update(self, request, *args, **kwargs):
        return APIResponse(msg='群改')

在settings.py配置文件中配置

REST_FRAMEWORK = 
    # 频率组件,频率类一般做局部配置,但是频率调节在settings中配置
    'DEFAULT_THROTTLE_RATES': 
        'user': '5/min',   # 登录用户限制
        'anon': '3/min',   # 匿名用户限制
    ,

自定义频率类

自定义频率类:

  • drf默认提供了一些频率类
    • AnonRateThrottle:只对游客进行频率限制
    • UserRateThrottle:对所有用户进行频率限制
  • 如果由特殊需要,需要自定义频率类
    • 如:对ip进行限次、对电话进行限次、对视图某些信息进行限次

方法步骤:

  • 设置scope字符串类属性,同时在settings中进行drf配置DEFAULT_THROTTLE_RATES
  • 重写get_catch_key方法
    • 返回与限制条件有关的字符串,表示限制
    • 返回None,表示不限制
# throttles.py

from rest_framework.throttling import SimpleRateThrottle

class MobileReateThrottle(SimpleRateThrottle):

    scope = 'mobile'
    def get_cache_key(self, request, view):
        if not request.user.is_authenticated or not request.user.mobile:
            return None   # 匿名用户   没有电话号的用户都不限制

        return self.cache_format % 
            'scope': self.scope,
            'ident': request.user.mobile
        

drf-jwt认证组件权限组件频率组件的使用(代码片段)

...组件频率组件drf-jwt签发token源码分析自定义签发token实现多方式登录源码分析多方式登陆签发token实例频率组件自定义频率类drf-jwt认证组件、权限组件、频率组件的使用三大认证流程图:认证组件在restframework中自带认证组件,而... 查看详情

签发token校验token多方式登录签发token的实现自定义认证反爬规则的认证类admin使用自定义user表:新增用户密码密文群查接口各种筛选组件数据准备drf搜索过滤组件drf排(代码片段)

签发token源码入口#前提:给一个局部禁用了所有认证与权限的视图类发送用户信息得到token,其实就是登录接口#1)rest_framework_jwt.views.ObtainJSONWebToken的父类JSONWebTokenAPIView的post方法#接收有username、password的post请求#2)post方法将请... 查看详情

drf认证组件权限组件jwt认证签发jwt框架使用(代码片段)

...pyserializers.py四、图书资源接口urls.pyviews.pyserializers.py五、认证组件重点自定义认证类六、权限组件重点自定义权限类七、jwt认证示意图八、jwt认证算法:签发与校验签发:根据登录请求提交来的账号+密码+设备信息签发token校验... 查看详情

79-drf三大认证的配置及使用方法(代码片段)

...份认证类(需要自定义签发token时用)5、自定义签发token及多方式登陆二、权限认证1、权限认证配置2、drf提供的权限认证类3、自定义权限认证类三、节流认证(频率认证)1、节流认证配置2、drf提供的节流认证类3、自定义节流认证类... 查看详情

drf之文档生成和jwt(代码片段)

...回的数据格式3.4自定义基于jwt的权限类3.5手动签发token(多方式登录)3.6jwt的配置参数1自定制频率#自定制频率类,需要写两个方法 -#判断是否限次:没有限次可以请求True,限次了不可以请求False defallow_request(self,re 查看详情

认证组件(代码片段)

目录认证组件认证组件项目使用:多方式登陆认证组件重点1认证规则2如何自定义认证类3我们一般不需要自定义认证类,在settings中全局配置第三方jwt认证组件提供的认证类即可自定义认证类1自定义认证类,继承BaseAuthentication类... 查看详情

drf08(代码片段)

目录三大认证流程认证组件权限组件频率组件自定义token的签发三大认证流程由于DRF中,所有的视图类都要直接和间接继承APIView类,也只有APIView类中才有dispatch方法,所以所有的请求都要经过三大认证,认证通过后执行相应请求的视... 查看详情

drf框架8系统权限类使用用户中心信息自查token刷新机制认证组件项目使用:多方式登录权限组件项目使用:vip用户权限频率组件异常组件项目使用(代码片段)

系统权限类使用图书接口:游客只读,用户可增删改查权限使用fromrest_framework.permissionsimportIsAuthenticatedOrReadOnlyclassBookViewSet(ModelViewSet):#游客只读,用户可增删改查permission_classes=[IsAuthenticatedOrReadOnly]queryset=models.Book.objects.all()seriali... 查看详情

drf--认证,权限,限制(代码片段)

 认证、权限和限制身份验证是将传入请求与一组标识凭据(例如请求来自的用户或其签名的令牌)相关联的机制。然后权限和限制组件决定是否拒绝这个请求。简单来说就是:认证确定了你是谁权限确定你能不能访问某个接... 查看详情

drf认证权限频率(代码片段)

目录一认证Authentication认证源码分析自定义认证方案二权限Permissions源码分析使用内置提供的权限举例自定义权限三限流Throttling使用实列可选限流类实例自定义频率类一认证Authentication认证组件:校验用户-游客、合法用户、非法... 查看详情

djangorestframework之认证组件,权限组件,频率组件(代码片段)

一.认证组件我们现在知道的认证机制有cookie,session,session比较安全,session的信息是存在服务器上的,如果用户量足够大的话,服务器的压力也就比较大,并且django的session存到了django_session表中,不是很好操作,现在生产中使用的一个叫... 查看详情

django自定义auth模块方式(代码片段)

...户模块的子应用创建自定义的用户模型类Django默认提供了认证系统Auth模块,认证的时候,会使用auth模块里面给提供的表。认证系统包含:用户管理权限用户组密码哈希系统用户登录或内容显示的表单和视图一个可插拔的后台系... 查看详情

drf的认证(代码片段)

一、概述认证是将传入请求与一组标识凭据(例如请求来自的用户或其签名的令牌)相关联的机制。然后权限和限制组件决定是否拒绝这个请求。简单来说就是:认证确定了你是谁权限确定你能不能访问某个接口限制确定你访问... 查看详情

认证权限频率自定义

fromrest_framework.authenticationimportBaseAuthenticationfromrest_framework.permissionsimportBasePermissionfromrest_framework.throttlingimportBaseThrottle,SimpleRateThrottlefromdjango_redisimportget_r 查看详情

springsecurity自定义登录认证

一、前言本篇文章将讲述SpringSecurity自定义登录认证校验用户名、密码,自定义密码加密方式,以及在前后端分离的情况下认证失败或成功处理返回json格式数据温馨小提示:SpringSecurity中有默认的密码加密方式以及登录用户认证... 查看详情

三大认证之认证组件和权限组件(代码片段)

...uest,*args,**kwargs)2.dispath方法内self.initial(request,*args,**kwargs)#认证组件:校验用户-游客,合法用户,非法用户#游客:代表着校验已经通过,直接进入下一步校验(权限校验)#合法用户:代表校验通过,将数据保存在request.user中,在进行下一步校... 查看详情

drf框架——drf-jwt手动签发与校验过滤组件筛选组件排序组件分页组件(代码片段)

...发和校验签发token源码入口前提:给一个局部禁用了所有认证与权限的视图类发送用户信息得到token,其实就是登录接口,不然进不了登录页面获取提交的username和password1)rest_framework_jwt.views.ObtainJSONWebToken的父类JSONWebTokenAPIView的p... 查看详情

[springsecurity]web权限方案_用户认证_自定义用户登录页面(代码片段)

在配置类中实现相关的配置@Overrideprotectedvoidconfigure(HttpSecurityhttp)throwsExceptionhttp.formLogin()//自定义自己编写的登陆页面.loginPage("/login.html")//登陆页面设置.loginProcessingUrl("/user/login")//登陆访问路 查看详情