rest_framework 认证与权限
一 认证
1.1先写个类(认证组件)
from app01 import models from rest_framework import exceptions from rest_framework.authentication import BaseAuthentication # 用drf的认证,写一个类,可以继承BaseAuthentication,也可以不用 # class LoginAuth(BaseAuthentication): class LoginAuth(): # 函数名一定要叫authenticate,接收必须两个参数,第二个参数是request对象 def authenticate(self, request): # 从request对象中取出token(也可以从其它地方取) token = request.query_params.get('token') # 去数据库过滤,查询 ret = models.UserToken.objects.filter(token=token) if ret: # 能查到,说明认证通过,返回空 # ret.user就是当前登录用户对象,一旦retrun了,后面的认证类都不执行了 return ret.user,ret # 如果查不到,抛异常 raise exceptions.APIException('您认证失败')
1.2views
def get_token(name): # 生成一个md5对象 md5 = hashlib.md5() # 往里添加值,必须是bytes格式 # time.time()生成时间戳类型,转成字符串,再encode转成bytes格式 md5.update(str(time.time()).encode('utf-8')) md5.update(name.encode('utf-8')) return md5.hexdigest() # 登录 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更新或者创建 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) class Books(APIView): # 列表中,类名不能加括号 # authentication_classes = [LoginAuth, ] def get(self, request, *args, **kwargs): # 只要通过认证,就能取到当前登录用户对象 print(request.user) response = {'status': 100, 'msg': '查询成功'} ret = models.Book.objects.all() book_ser = MySerializer.BookSerializer(ret, many=True) response['data'] = book_ser.data return JsonResponse(response, safe=False)
1.3局部配置,全局配置,局部禁用
1.3.1局部配置
class Books(APIView): # 列表中,类名不能加括号 # 局部配置,就是在需要认证功能的视图函数下加 authentication_classes = [LoginAuth, ]
1.3.2全局配置
# 在settings中配置 REST_FRAMEWORK={ 'DEFAULT_AUTHENTICATION_CLASSES':['app01.MyAuth.LoginAuth',], #认证 'DEFAULT_PERMISSION_CLASSES':['app01.MyAuth.Permission',] #权限 }
1.3.3局部禁用
class Books(APIView): # 列表中,类名不能加括号 # 局部禁用,就是在需要认证功能的视图函数下的authentication_classes的列表置空 authentication_classes = [ ]
1.4认证的顺序
认证类使用顺序:先用视图类中的验证类,再用settings里配置的验证类,最后用默认的验证类
二 权限
2.1写一个类(权限组件)
class UserPermission(BasePermission): # message是出错显示的中文 message='您没有权限查看' def has_permission(self, request, view): user_type = request.user.user_type # 取出用户类型对应的文字 # 固定用法:get_字段名字_display() user_type_name = request.user.get_user_type_display() print(user_type_name) if user_type == 2: return True else: return False
2.2权限的简单使用(views)
# 需求,只能超级用户来查看作者详情,其他人不能看 from app01.MyAuth import UserPermission class Authors(APIView): # permission_classes=[UserPermission,] # 局部禁用: permission_classes = [] def get(self, request, *args, **kwargs): response = {'status': 100, 'msg': '查询成功'} ret = models.Author.objects.all() ser = MySerializer.AuthorSerializer(ret, many=True) response['data'] = ser.data return JsonResponse(response, safe=False)
2.3局部配置,全局配置,局部禁用
- 与认证用法相同
2.4权限使用顺序
权限类使用顺序:先用视图类中的权限类,再用settings里配置的权限类,最后用默认的权限类
三 不用再数据库中查询token的认证
不在数据库中存token验证思路:
在查看网站信息的时候要登录的,在登录的时候后台在拿到token,token是由加密算法函数中传入查询对象的id(或其他信息)产生的随机字符串.查看信息时,拿着这个与id(或其他信息)与随机字符串拼接的密文,在后台通过切分密文到查询对象的id(或其他信息),然后通过同样的算法得到随机字符串,比对他们是否相等