一、认证组件

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

二、局部使用

(1)models层

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。 认证组件 Python 第1张
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 两个参数)

认证组件 Python 第3张
# 用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层

认证组件 Python 第5张
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验证

认证组件 Python 第7张
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, ]

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄