zoukankan      html  css  js  c++  java
  • 认证组件

    简单实例

    settings.py

    INSTALLED_APPS = [
        'rest_framework',
    ]
    

    urls.py

    urlpatterns = [
        path('admin/', admin.site.urls),
        path('api/v1/auth/',views.AuthView.as_view()),
    ]
    

    models.py

    from django.db import models
    
    class UserInfo(models.Model):
        USER_TYPE = (
            (1,'普通用户'),
            (2,'VIP'),
            (3,'SVIP')
        )
    
        user_type = models.IntegerField(choices=USER_TYPE)
        username = models.CharField(max_length=32)
        password = models.CharField(max_length=64)
    
    class UserToken(models.Model):
        user = models.OneToOneField(UserInfo,on_delete=models.CASCADE)
        token = models.CharField(max_length=64)
    

    views.py

    from django.shortcuts import render,HttpResponse
    from django.http import JsonResponse
    from rest_framework.views import APIView
    from API import models
    from rest_framework.request import Request
    from rest_framework import exceptions
    from rest_framework.authentication import BasicAuthentication
    
    ORDER_DICT = {
        1:{
            'name':'apple',
            'price':15
        },
        2:{
            'name':'dog',
            'price':100
        }
    }
    
    def md5(user):
        import hashlib
        import time
        #当前时间,相当于生成一个随机的字符串
        ctime = str(time.time())
        m = hashlib.md5(bytes(user,encoding='utf-8'))
        m.update(bytes(ctime,encoding='utf-8'))
        return m.hexdigest()
    
    class AuthView(object):
        '''用于用户登录验证'''
        def post(self,request,*args,**kwargs):
            ret = {'code':1000,'msg':None}
            try:
                user = request._request.POST.get('username')
                pwd = request._request.POST.get('password')
                obj = models.UserInfo.objects.filter(username=user,password=pwd).first()
                if not obj:
                    ret['code'] = 1001
                    ret['msg'] = '用户名或密码错误'
                #为用户创建token
                token = md5(user)
                #存在就更新,不存在就创建
                models.UserToken.objects.update_or_create(user=obj,defaults={'token':token})
                ret['token'] = token
            except Exception as e:
                ret['code'] = 1002
                ret['msg'] = '请求异常'
            return JsonResponse(ret)
    
    
    class Authentication(APIView):
        '''认证'''
        def authenticate(self,request):
            token = request._request.GET.get('token')
            token_obj = models.UserToken.objects.filter(token=token).first()
            if not token_obj:
                raise exceptions.AuthenticationFailed('用户认证失败')
            #在rest framework内部会将这两个字段赋值给request,以供后续操作使用
            return (token_obj.user,token_obj)
    
        def authenticate_header(self, request):
            pass
    
    class OrderView(APIView):
        '''订单相关业务'''
    
        authentication_classes = [Authentication,]    #添加认证
        def get(self,request,*args,**kwargs):
            #request.user
            #request.auth
            ret = {'code':1000,'msg':None,'data':None}
            try:
                ret['data'] = ORDER_DICT
            except Exception as e:
                pass
            return JsonResponse(ret)

    总结:

    	-写一个认证类(继承BaseAuthentication)
    		-重写authenticate方法,把request对象传入
    		-能从request对象中取出用户携带的token,根据token判断是否登录过
    		-如果登录过,返回两个值 user对象,token对象
    		-如果没有登录过抛异常
    	-全局使用
    		-在settings中配置
    			REST_FRAMEWORK={
                    "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",]
                    }
    	-局部使用
    		-在视图类中配置:
    			authentication_classes=[Authentication,]
    	-局部禁用:
    		-在视图类中配置:
    			authentication_classes=[]
    

      

    认证源码分析

    -APIView中的dispatch  --->  self.initial(认证,频率,权限) --->   self.perform_authentication(认证)  --->   本质又调用了新的request对象的user方法
      -->  request.user内部执行了:self._authenticate(注意self是新的request对象)  --->   循环拿到一个个认证类的对象,执行对象的authenticate方法,传入request对象
    --->   一个个认证类的对象是在reuqest对象实例化的时候传入的   --->   APIView中的get_authenticators,通过列表推导式生成一个个的认证类对象,然后传入request对象中

  • 相关阅读:
    NETCore EF 数据库连接正确nuget和MySql错误异常
    JS 对象属性名排序
    NET 在一个数组中查找另一个数组所在起始位置(下标从0开始,未找到返回-1)
    NET 判断是否为回文
    NET/Regex 处理连续空格
    NET 已知excel表格前面26个是a到z,27是aa28是ab,以此类推,N是多少
    Regex 首字母转大写/小写,全大写,全小写
    .NETCore下访问img、js等静态资源404解决办法
    WPF-后台代码使用Behavior
    Socket-服务器端与客户端互相通信
  • 原文地址:https://www.cnblogs.com/penghengshan/p/11134196.html
Copyright © 2011-2022 走看看