• 认证组件


    一、认证组件

      只有认证通过的用户才能访问指定的url地址,比如:查询课程信息,需要登录之后才能查询,没有登录就不能查看 ,这时候就要用到认证组件

    二、局部使用

    (1)models层

    class UserInfo(models.Model):
        name = models.CharField(max_length=32)
        user_choice = ((0, '普通用户'), (1, '会员'), (2, '超级用户'))
        # 指定choice,可以快速 的通过数字,取出文字
        user_type = models.IntegerField(choices=user_choice, default=0)
        pwd = models.CharField(max_length=32)
    
    
    class UserToken(models.Model):
        # token随机字符串
        token = models.CharField(max_length=64)
        user = models.OneToOneField(to=UserInfo)
    View Code

    (2)新建认证类(验证通过 return 两个参数)

    # 用drf的认证,写一个类
    class LoginAuth():
        # 函数名一定叫authenticate,接收 必须两个参数,第二个 参数是request对象
        def authenticate(self, request):
            # 从request对象中取出token(也可以从其他地方取)
            token = request.query_params.get('token')
            # 去数据库过滤,查询
            ret = models.UserToken.objects.filter(token=token).first()
            if ret:
                # 认证多个 ,用None ; authentication_classes = [LoginAuth, ]
                # return None
                return ret.user, ret
            # 如果查询不到抛异常
            raise exceptions.APIException('您认证失败')
    View Code

    (3)view层

    class Login(APIView):
        # 空,局部禁用
        authentication_classes = []
    
        def post(self, request, *args, **kwargs):
            response = {'status': 100, 'msg': '登录成功'}
            name = request.data.get('name')
            pwd = request.data.get('pwd')
            try:
                user = models.UserInfo.objects.get(name=name, pwd=pwd)
                # 校验通过,登录成功,生成一个随机字符串,token
                token = get_token(name)
                # 保存到数据库,update_or_create,有跟新,没有创建
                # 修改或新增的东西放在defaults中
                models.UserToken.objects.update_or_create(user=user, defaults={'token': token})
                response['token'] = token
            except ObjectDoesNotExist as e:
                response['status'] = 101
                response['msg'] = '用户名或密码错误'
            except Exception as e:
                response['status'] = 102
                # response['msg']='未知错误'
                response['msg'] = str(e)
            return JsonResponse(response, safe=False)
    View Code

    附:不存数据库的token验证

    def get_token(id,salt='123'):
        import hashlib
        md=hashlib.md5()
        md.update(bytes(str(id),encoding='utf-8'))
        md.update(bytes(salt,encoding='utf-8'))
    
        return md.hexdigest()+'|'+str(id)
    
    def check_token(token,salt='123'):
        ll=token.split('|')
        import hashlib
        md=hashlib.md5()
        md.update(bytes(ll[-1],encoding='utf-8'))
        md.update(bytes(salt,encoding='utf-8'))
        if ll[0]==md.hexdigest():
            return True
        else:
            return False
    
    class TokenAuth():
        def authenticate(self, request):
            token = request.GET.get('token')
            success=check_token(token)
            if success:
                return
            else:
                raise AuthenticationFailed('认证失败')
        def authenticate_header(self,request):
            pass
    class Login(APIView):
        def post(self,reuquest):
            back_msg={'status':1001,'msg':None}
            try:
                name=reuquest.data.get('name')
                pwd=reuquest.data.get('pwd')
                user=models.User.objects.filter(username=name,password=pwd).first()
                if user:
                    token=get_token(user.pk)
                    # models.UserToken.objects.update_or_create(user=user,defaults={'token':token})
                    back_msg['status']='1000'
                    back_msg['msg']='登录成功'
                    back_msg['token']=token
                else:
                    back_msg['msg'] = '用户名或密码错误'
            except Exception as e:
                back_msg['msg']=str(e)
            return Response(back_msg)
    from rest_framework.authentication import BaseAuthentication
    class TokenAuth():
        def authenticate(self, request):
            token = request.GET.get('token')
            token_obj = models.UserToken.objects.filter(token=token).first()
            if token_obj:
                return
            else:
                raise AuthenticationFailed('认证失败')
        def authenticate_header(self,request):
            pass
    
    class Course(APIView):
        authentication_classes = [TokenAuth, ]
    
        def get(self, request):
            return HttpResponse('get')
    
        def post(self, request):
            return HttpResponse('post')
    View Code

    三、全局使用

    REST_FRAMEWORK={
        'DEFAULT_AUTHENTICATION_CLASSES':['app01.MyAuth.LoginAuth',],
        'DEFAULT_PERMISSION_CLASSES':['app01.MyAuth.UserPermission',]
    }

    总结:局部使用,只需要在视图类加入:

    authentication_classes = [TokenAuth, ]
  • 相关阅读:
    CF1187E Tree Painting
    [TJOI2017]城市
    [HNOI2010]合唱队
    2020暑假多校补题记录
    树形dp总结
    2017CCPC 秦皇岛 G. Numbers (贪心 + java大数)
    LOJ 2491 求和 (LCA + 前缀和)
    LOJ 10105. 欧拉回路
    Luogu P3953 逛公园 (最短路+dp)
    LOJ#2718. 「NOI2018」归程 (kruskal重构树)
  • 原文地址:https://www.cnblogs.com/xuecaichang/p/10116223.html
Copyright © 2020-2023  润新知