Rest-framework之drf认证组件,权限组件
django中一个请求时一个reques,如果在哪个位置改了request,那么到了后面就是修改过的request
昨日回顾:
认证:
-写一个认证类,(可以继承BaseAuthentication)
-注意:这个类要放在单独的py文件中,(如果放在view中,全局配置无法使用)
-类中写个函数:def authenticate(self,request)
-认证的判断:
-取出token做验证
-验证通过,可以返回两个值,一个给了request.user,一个给了request.auth
-验证不通过,抛异常
-因为认证类可以写多个,如果想让多个都执行,放在前面的不能return值
-局部使用:
-在视图类中
authentication_classes = [LoginAuth, ]
-全局使用:
-在setting中配置
-REST_FRAMEWORK={
'DEFAULT_AUTHENTICATION_CLASSES':['app01.MyAuth.LoginAuth',],
}
-局部禁用:
-在视图类中
authentication_classes = [ ]
权限:
-写一个权限类,(可以继承BasePermission)
-注意:这个类要放在单独的py文件中,(如果放在view中,全局配置无法使用)
-类中的方法:def has_permission(self,request,view)
-认证通过:返回True
-认证不通过:返回False
-返回值:布尔类型
-局部使用:
-在视图类中:
-permission_classes = [UserPermission,]
-全局使用:
-在setting中配置
-REST_FRAMEWORK={
'DEFAULT_PERMISSION_CLASSES':['app01.MyAuth.UserPermission',]
}
-局部禁用:
-在视图类中:
-permission_classes = []
choice的用法:
-拿出数字对应的中文:get_字段名_dispaly()
因为认证类可以写多个,如果想要多个都执行,放在前面的就不能return值,可以return None
1.views视图层
from django.shortcuts import render from rest_framework.views import APIView from app01 import models from django.core.exceptions import ObjectDoesNotExist import hashlib import time from django.http import JsonResponse from app01 import MySerializer from rest_framework.request import Request from rest_framework import exceptions def get_token(name): md5 = hashlib.md5() # 生成一个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 = [] # 登录就是使用post,get是返回一个页面 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) # 保存到数据库 # user=user就是需要查询的数据,defaults里面:token就是需要修改或者新增的数据 models.UserToken.objects.update_or_create(user=user, defaults={'token': token}) # 登陆成功之后把登录返回给他,以后就带着token过来 response['token'] = token except ObjectDoesNotExist as e: response['status'] = 101 response['msg'] = '用户名或密码错误' except Exception as e: # 万能异常,里面只要出错,程序就会走到这里 response['status'] = 102 # response['msg'] = '未知错误' # 把整个错误信息转换成str类型,赋值给e,一般在测试时使用这个 response['msg'] = str(e) # 如果不写safe=False,只能序列化字典形式,如果字典里面又套了列表,或者直接是一个列表,就必须写safe=False return JsonResponse(response, safe=False) from app01.MyAuth import LoginAuth class Books(APIView): # 列表中类名不能加括号 authentication_classes = [LoginAuth, ] def get(self, request, *args, **kwargs): # 只要通过认证,就能取到当前登录用户对象的密码,id等信息 # print(request.query_params) # print(request.user.name) # print(request.user.pwd) response = {'status': 100, 'msg': '查询成功'} res = models.Book.objects.all() book_ser = MySerializer.BookSerializer(res, many=True) # 这个数据是需要返回给前台的 response['data'] = book_ser.data # print(book_ser.data) return JsonResponse(response, safe=False) # 需求:只能黄金会员才能查看作者详情,其他会员不能看 from app01.MyAuth import UserPermission class Authors(APIView): # permission_classes = [UserPermission,] # 局部禁用 permission_classes = [] def get(self, request, *args, **kwargs): response = {'status': 100, 'msg': '查询成功'} author_all = models.Author.objects.all() author_ser = MySerializer.AuthorSerializer(author_all, many=True) response['data'] = author_ser.data return JsonResponse(response, safe=False) class User(APIView): def get(self, request, *args, **kwargs): response = {'status': 100, 'msg': '查询成功'} user_all = models.UserInfo.objects.all() user_ser = MySerializer.UserSerializer(user_all, many=True) response['data'] = user_ser.data return JsonResponse(response, safe=False)
2.MyAuth.py-认证组件和权限组件
from app01 import models from rest_framework import exceptions from rest_framework.authentication import BaseAuthentication # 认证组件,使用drf的认证,我们需要写一个类 class LoginAuth(BaseAuthentication): # 函数名一定要叫authenticate,需要接收2个参数,第二个参数是request对象 def authenticate(self, request): # 从request对象中取出token(也可以从其他地方取) token = request.query_params.get('token') # 去数据库过滤,查询 ret = models.UserToken.objects.filter(token=token).first() if ret: # 能查到,说明认证通过,反回空 # ret.user就是当前登录用户对象 return ret.user, ret # 如果查不到,就抛出异常 raise exceptions.APIException('认证失败') #权限组件,谁有资格查看作者详情信息 class UserPermission(): # message是错误显示的中文 message = '您没有权限查看' def has_permission(self, request, view): user_type = request.user.user_type # print(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
3.MySerializer.py-序列化组件
from rest_framework import serializers from app01 import models class BookSerializer(serializers.ModelSerializer): class Meta: model = models.Book fields = '__all__' class AuthorSerializer(serializers.ModelSerializer): class Meta: model = models.Author fields = '__all__' class UserSerializer(serializers.ModelSerializer): class Meta: model = models.UserInfo fields = '__all__' user_type=serializers.CharField(source='get_user_type_display') # user_type = serializers.SerializerMethodField() # def get_user_type(self, obj): # return obj.get_user_type_display()
4.models层
from django.db import models # Create your models here. # 用户信息 class UserInfo(models.Model): name = models.CharField(max_length=32) pwd = models.CharField(max_length=32) # 写choice user_choice = ((0, '普通会员'), (1, '铂金会员'), (2, '黄金会员')) # 指定choice,可以快速的通过数字,取出文字 user_type = models.IntegerField(choices=user_choice,default=0) # 用户token class UserToken(models.Model): token = models.CharField(max_length=64) user = models.OneToOneField(to='UserInfo') class Book(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) price = models.DecimalField(max_digits=5, decimal_places=2) publish_date = models.DateField() publish = models.ForeignKey(to='Publish', to_field='nid', on_delete=models.CASCADE) # 删除关联数据,与之关联也删除 authors = models.ManyToManyField(to='Author') def __str__(self): return self.name class Author(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) age = models.IntegerField() author_detail = models.OneToOneField(to='AuthorDetail', to_field='nid', unique=True, on_delete=models.CASCADE) class AuthorDetail(models.Model): nid = models.AutoField(primary_key=True) telephone = models.BigIntegerField() birthday = models.DateField() addr = models.CharField(max_length=64) def __str__(self): return self.telephone class Publish(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) city = models.CharField(max_length=32) email = models.EmailField() def __str__(self): return self.name def test(self): return self.email
5.settings.py
全局使用认证和权限 REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ['app01.MyAuth.LoginAuth', ], 'DEFAULT_PERMISSION_CLASSES': ['app01.MyAuth.UserPermission', ] }
6.urls.py路由层
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/', views.Login.as_view()), url(r'^books/', views.Books.as_view()), url(r'^authors/', views.Authors.as_view()), url(r'^users/', views.User.as_view()), ]
7.不存数据库的token认证
粗糙的丸子 博客园 首页 新随笔 联系 订阅 管理 随笔 - 18 文章 - 2 评论 - 0 哇哇哇哇 1.不存数据库的token认证 import hashlib from day98 import settings def check_token(token): ret = True user_info = None try: ll = token.split('|') # da89744b701b5d8bc5b9a76b4ddb3dd4 , {"name": "cao", "id": 1},已经切分成了一个列表 md5 = hashlib.md5() # 需要给这个{"name": "cao", "id": 1}加密,它就是列表里的第一个值 md5.update(ll[1].encode('utf-8')) # 在setting里面全局配置一下,给token加盐 md5.update(settings.password.encode('utf-8')) # hex=da89744b701b5d8bc5b9a76b4ddb3dd4 hex = md5.hexdigest() if not hex == ll[0]: ret = False else: user_info = ll[1] except Exception as e: ret = False return ret, user_info class LoginAuth(BaseAuthentication): # 函数名一定要叫authenticate,需要接收2个参数,第二个参数是request对象 def authenticate(self, request): # 从request对象中取出token(也可以从其他地方取) token = request.query_params.get('token') # ret是布尔类型,表示验证通过或者失败,user_info是user的字典 ret, user_info = check_token(token) if ret: # 能查到,说明认证通过,反回空 # ret.user就是当前登录用户对象 return user_info, None # 如果查不到,就抛出异常 raise exceptions.APIException('认证失败') View.py-登录接口 好文要顶 关注我 收藏该文 粗糙的丸子 关注 - 6 粉丝 - 0 0 0 « 上一篇:Rest-framework之drf认证组件,权限组件 posted @ 2018-12-14 16:45 粗糙的丸子 阅读(0) 评论(0) 编辑 收藏 刷新评论刷新页面返回顶部 发表评论 昵称: 评论内容: 退出 [Ctrl+Enter快捷键提交] 【推荐】超50万VC++源码: 大型组态工控、电力仿真CAD与GIS源码库! 【活动】华为云12.12会员节全场1折起 满额送Mate20 【活动】华为云会员节云服务特惠1折起 【活动】腾讯云+社区开发者大会12月15日首都北京盛大起航! 相关博文: · 哇哇cool~~~ · 呜哇哇,呜嘛嘛 · 哇哇哇~~ · Linux常用命令大全 · java网络编程Socket通信详解 最新新闻: · 消失的90后CEO与赌场资本主义年代 · 从孟晚舟职场二三事说起 · 微软可穿戴设备专利曝光:有望改善帕金森患者手部的颤抖影响 · 知乎架构调整:提高组织力 任命前蜜芽合伙人为CFO · Apple Music有个功能被苹果砍掉了,但你可能从未用过它 » 更多新闻... 公告 github com/粗糙的丸子 邮箱: 2120176410@gq.com 微信(QQ) : 2120176410 昵称:粗糙的丸子 园龄:4个月 粉丝:0 关注:6 < 2018年12月 > 日 一 二 三 四 五 六 25 26 27 28 29 30 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 1 2 3 4 5 搜索 常用链接 我的随笔 我的评论 我的参与 最新评论 我的标签 随笔档案 2018年12月 (5) 2018年11月 (5) 2018年10月 (1) 2018年9月 (7) 2018年8月 (1) 阅读排行榜 1. 小红书要求的技能掌握(熟悉RESTful服务,深刻理解mvc,oop, Aop概念)(29) 2. python题目-----search()和match()的区别(19) 3. mysql表操作之完整性约束(18) 4. css的三大特性继承性,层叠行,优先级(17) 5. Json模块dumps、loads、dump、load函数介绍(16) Copyright ©2018 粗糙的丸子
class Books(APIView): # 列表中类名不能加括号 authentication_classes = [LoginAuth, ] def get(self, request, *args, **kwargs): # 只要通过认证,就能取到当前登录用户对象的密码,id等信息 # print(request.query_params) print(request.user) # print(request.user.pwd) response = {'status': 100, 'msg': '查询成功'} res = models.Book.objects.all() book_ser = MySerializer.BookSerializer(res, many=True) # 这个数据是需要返回给前台的 response['data'] = book_ser.data # print(book_ser.data) return JsonResponse(response, safe=False) # 登录接口,不存数据库的token认证 import json from day98 import settings def create_token(user_pk): md5 = hashlib.md5() md5.update(user_pk.encode('utf-8')) # 在setting里面全局配置一下,给token加盐 md5.update(settings.password.encode('utf-8')) hex = md5.hexdigest() token = '|'.join([hex, user_pk]) # token=hex+'|'+user_info print(token) return token class Login(APIView): authentication_classes = [] # 登录就是使用post,get是返回一个页面 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) user_info_json = json.dumps({'name': user.name, 'id': user.pk}) # 生成vfvevberber|{'name': user.name, 'id': user.pk}的token token = create_token(str(user.pk)) # 登陆成功之后把登录返回给他,以后就带着token过来 response['token'] = token except ObjectDoesNotExist as e: response['status'] = 101 response['msg'] = '用户名或密码错误' except Exception as e: # 万能异常,里面只要出错,程序就会走到这里 response['status'] = 102 # response['msg'] = '未知错误' # 把整个错误信息转换成str类型,赋值给e,一般在测试时使用这个 response['msg'] = str(e) # 如果不写safe=False,只能序列化字典形式,如果字典里面又套了列表,或者直接是一个列表,就必须写safe=False return JsonResponse(response, safe=False) View.py-登录接口