一、认证组件
只有认证通过的用户才能访问指定的url地址,比如:查询课程信息,需要登录之后才能查询,没有登录就不能查看 ,这时候就要用到认证组件
二、局部使用
(1)models层
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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)
(2)新建认证类(验证通过 return 两个参数)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 用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('您认证失败')
(3)view层
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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)
附:不存数据库的token验证
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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')
三、全局使用
REST_FRAMEWORK={ 'DEFAULT_AUTHENTICATION_CLASSES':['app01.MyAuth.LoginAuth',], 'DEFAULT_PERMISSION_CLASSES':['app01.MyAuth.UserPermission',] }
总结:局部使用,只需要在视图类加入:
authentication_classes = [TokenAuth, ]