一、认证组件

  只有认证通过的用户才能访问指定的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. s.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. s.get(name=name, pwd=pwd)
            # 校验通过,登录成功,生成一个随机字符串,token
            token = get_token(name)
            # 保存到数据库,update_or_create,有跟新,没有创建
            # 修改或新增的东西放在defaults中
            models.UserToken. s.update_or_create(user=user, defaults={\'token\': token})
            response[\'token\'] = token
        except  DoesNotExist 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. s.filter(username=name,password=pwd).first()
            if user:
                token=get_token(user.pk)
                # models.UserToken. s.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_ work.authentication import  Authentication
class TokenAuth():
    def authenticate(self, request):
        token = request.GET.get(\'token\')
        token_obj = models.UserToken. s.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_ WORK={
    \'DEFAULT_AUTHENTICATION_CLASSES\':[\'app01.MyAuth.LoginAuth\',],
    \'DEFAULT_PERMISSION_CLASSES\':[\'app01.MyAuth.UserPermission\',]
}

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

authentication_classes = [TokenAuth, ]

 

收藏 打印