认证、权限和限制

身份验证是将传入请求与一组标识凭据(例如请求来自的用户或其签名的令牌)相关联的机制。然后 权限 和 限制 组件决定是否拒绝这个请求。

简单来说就是:

认证确定了你是谁

权限确定你能不能访问某个接口

限制确定你访问某个接口的频率

认证

REST framework 提供了一些开箱即用的身份验证方案,并且还允许你实现自定义方案。

个人 敲码log:

1.

  1. # Create your models here.
  2. class UserInfo1(models.Model):
  3. id = models.AutoField(primary_key=True) # 创建一个自增的主键字段
  4. # 创建一个varchar(64)的唯一的不为空的字段
  5. name = models.CharField(null=False, max_length=20)
  6. pwd = models.CharField(max_length=32,default=123)
  7.  
  8. class Token(models.Model):
  9. user = models.OneToOneField("UserInfo1",on_delete=models.CASCADE)
  10. token = models.CharField(max_length=128)

2.

  1. # 我需要一个随机字符串
  2. def get_random_str(user):
  3. import hashlib, time
  4. ctime = str(time.time())
  5. # 封装bytes类型一个MD5的加密对象
  6. md5 = hashlib.md5(bytes(user, encoding="utf8"))
  7. # md5.update 是拼接的效果,随机生成md5值
  8. md5.update(bytes(ctime, encoding="utf8"))
  9. return md5.hexdigest()
  10.  
  11. # 认证、权限和限制
  12. class LoginModelView(APIView):
  13. def post(self, request):
  14. name = request.data.get("name")
  15. pwd = request.data.get("pwd")
  16.  
  17. user = models.UserInfo1.objects.filter(name=name, pwd=pwd).first()
  18. res = {"state_code": 1000, "msg": None}
  19. if user:
  20. # 返回了一个usermd5 加密的字符串
  21. random_str = get_random_str(user.name)
  22. """
  23. 当存在token时,则更新,不存在则创建,defaults: 是由 (field, value) 对组成的字典,用于更新对象。
  24. 返回一个由 (object, created)组成的元组,
  25. object: 是一个创建的或者是被更新的对象,
  26. created: 是一个标示是否创建了新的对象的布尔值。
  27. """
  28. token = models.Token.objects.update_or_create(user=user, defaults={"token": random_str})
  29. res["token"] = random_str
  30. else:
  31. res["state_code"] = 1001 # 错误状态码
  32. res["msg"] = "用户名或者密码错误"
  33.  
  34. import json
  35. # 这是因为json.dumps 序列化时对中文默认使用的ascii编码.想输出真正的中文需要指定ensure_ascii=False:
  36. # 如果你这样的话就能把中文转成json字符串,而不是 \u4e2d\u56fd
  37. return Response(json.dumps(res,ensure_ascii=False))

Django update_or_create 分析

update_or_create(defaults=None, **kwargs)
defaults 的值不同则创建,相同则更新

Member.objects.update_or_create(defaults={'user':1}, others={'field1':1,'field2':1})
当存在user=1时,则更新,不存在则创建

update_or_create 用法:

update_or_create(defaults=None, **kwargs)

kwargs: 来更新对象或创建一个新的对象。

defaults: 是由 (field, value) 对组成的字典,用于更新对象。

返回一个由 (object, created)组成的元组,

object: 是一个创建的或者是被更新的对象,

created: 是一个标示是否创建了新的对象的布尔值。

update_or_create: 方法通过给出的kwarg

定义一个认证类(详情请看 源码分析)

好处:

1.他能判断你是否是当前登录用户,当你没有带认证码 向我后端发请求的时候我是不会给你数据的。

2.他每一次登录的认证都会改变。

局部视图认证

示例1:

  1. class TokenAuth(object):
  2. def authenticate(self, request):
  3. # 取到 request里面的 token值
  4. totken = request.GET.get("token")
  5. token_obj = models.Token.objects.filter(token=totken).first()
  6. if not token_obj:
  7. # 抛认证字段的异常
  8. raise exceptions.AuthenticationFailed("验证失败")
  9. else:
  10. return token_obj.user.name,token_obj.token
  11.  
  12. def authenticate_header(self,request):
  13. pass
  1. # 多条数据
  2. class BookView(APIView):
  3. # 定义一个认证类
  4. authentication_classes = [TokenAuth]

而没有定义 token类的依然可以访问。

全局级别认证

  1. # 定义全局认证,所有视图都需要认证
  2. REST_FRAMEWORK = {
  3. "DEFAULT_AUTHENTICATION_CLASSES" : ["app01.utils.TokenAuth"]
  4.  
  5. }

  1. from app01 import models
  2. from rest_framework import exceptions
  3.  
  4. class TokenAuth(object):
  5. def authenticate(self, request):
  6. # 取到 request里面的 token值
  7. totken = request.GET.get("token")
  8. token_obj = models.Token.objects.filter(token=totken).first()
  9. if not token_obj:
  10. # 抛认证字段的异常
  11. raise exceptions.AuthenticationFailed("验证失败")
  12. else:
  13. return token_obj.user.name, token_obj.token
  14.  
  15. def authenticate_header(self, request):
  16. pass

权限

只有VIP用户才能看的内容。

  1. from rest_framework.permissions import BasePermission
  2. class SVIPPermission(BasePermission):
  3. message="只有超级用户才能访问"
  4. def has_permission(self,request,view):
  5. username=request.user
  6. user_type=User.objects.filter(name=username).first().user_type
  7.  
  8. if user_type==3:
  9.  
  10. return True # 通过权限认证
  11. else:
  12. return False
  1. # 封装了3层
  2. class AuthorDetaiView(viewsets.ModelViewSet):
  3. permission_classes = [SVIPpermission,]
  4. throttle_classes = [] # 限制某个ip 每分钟访问次数不能超过20次
  5. # authentication_classes = [TokenAuth]
  6. # queryset serializer 这两个方法一定要定义成这个不然取不到值
  7. queryset = models.Author.objects.all()
  8. serializer_class = AuthorModelSerializers

限制(频率组件)

# 自定义局部限制

  1. import time
  2.  
  3. # 自定义限制
  4. VISIT_RECORD = {}
  5. class VisitRateThrottle(object):
  6. def __init__(self):
  7. self.history = None
  8.  
  9. def allow_request(self, request, view):
  10.  
  11. """
  12. 自定义频率限制60秒内只能访问三次
  13. """
  14. # 获取用户IP
  15. ip = request.META.get("REMOTE_ADDR")
  16. # 获取当前时间戳
  17. timestamp = time.time()
  18.  
  19. # 如果当前访问ip没有在列表中 我就新建一个IP访问记录
  20. if ip not in VISIT_RECORD:
  21. VISIT_RECORD[ip] = [timestamp, ]
  22. # 可以通过验证
  23. return True
  24.  
  25. # 如果列表中有值,我就取当当前ip地址 赋值给变量
  26. history = VISIT_RECORD[ip]
  27. self.history = history
  28. # 在列表头部 插入一个时间戳
  29. history.insert(0, timestamp)
  30. # 如果列表有值,最先插入的值小于 当前值-60 ,tiemstamp是当前时间是在增加的
  31. while history and history[-1] < timestamp - 60:
  32. # pop 取出 最后一个条件成立的值
  33. history.pop()
  34. # 列表中的时间戳 大于3 就返回falsse,否则通过
  35. if len(history) > 3:
  36. return False
  37. else:
  38. return True
  39.  
  40. def wait(self):
  41. # 返回给前端还剩多少时间可以访问
  42. timestamp = time.time()
  43. # 求出还剩多少时间可以访问
  44. return 60 - (timestamp - self.history[-1])
  1. # 视图使用
    from rest_framework.response import Response
  2.  
  3. class AuthorModelView(viewsets.ModelViewSet):
  4. authentication_classes = [TokenAuth, ]
  5. permission_classes = [SVIPPermission, ]
  6. throttle_classes = [VisitRateThrottle, ] # 限制某个IP每分钟访问次数不能超过20次
  7. queryset = Author.objects.all()
  8. serializer_class = AuthorModelSerializers
  9. # 分页
  10. # pagination_class = MyPageNumberPagination
  11. # renderer_classes = []

# 全局使用

  1. # 在settings.py中设置rest framework相关配置项
  2. REST_FRAMEWORK = {
  3. "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.TokenAuth", ],
  4. "DEFAULT_PERMISSION_CLASSES": ["app01.utils.SVIPPermission", ],
  5. "DEFAULT_THROTTLE_CLASSES": ["app01.utils.MyThrottle", ],
  6. }

二:内置频率类的使用

定义频率类,必须继承SimpleRateThrottle类:

  1. from rest_framework.throttling import SimpleRateThrottle
  2. class VisitThrottle(SimpleRateThrottle):
    # 必须配置scope参数 通过scope参数去settings中找频率限定的规则
  3. scope = 'throttle'
    # 必须定义 get_cache_key函数 返回用户标识的key 这里借用源码中BaseThrottle类(SimpleRateThrottle的父类)中的get_ident函数返回用户ip地址
  4. def get_cache_key(self, request, view):
  5. return self.get_ident(request)

局部使用:

  1. 视图函数中加上
    throttle_classes = [VisitThrottle,]

全局使用:settings中配置

  1. REST_FRAMEWORK={
  2. 'DEFAULT_THROTTLE_CLASSES':['utils.common.VisitThrottle'],
    # 局部使用也要在settings中配置上 DEFAULT_THROTTLE_RATES 通过self.scope取频率规则 (一分钟访问3次)
  3. 'DEFAULT_THROTTLE_RATES':{'throttle':'3/m',}
  4. }

设置错误信息为中文:

  1. class Course(APIView):
  2. authentication_classes = [TokenAuth, ]
  3. permission_classes = [UserPermission, ]
  4. throttle_classes = [MyThrottles,]
  5.  
  6. def get(self, request):
  7. return HttpResponse('get')
  8.  
  9. def post(self, request):
  10. return HttpResponse('post')
  11. # 函数名为throttled 重写Throttled类中默认的错误信息
  12. def throttled(self, request, wait):
  13. from rest_framework.exceptions import Throttled
  14. class MyThrottled(Throttled):
  15. default_detail = '访问频繁'
  16. extra_detail_singular = '等待 {wait} second.'
  17. extra_detail_plural = '等待 {wait} seconds.'
  18. raise MyThrottled(wait)

Django REST framework认证权限和限制和频率的更多相关文章

  1. Django REST Framework 认证 - 权限 - 限制

    一. 认证 (你是谁?) REST framework 提供了一些开箱即用的身份验证方案,并且还允许你实现自定义方案. 自定义Token认证 第一步 : 建表>>>> 定义一个 ...

  2. Django REST framework认证权限和限制 源码分析

    1.首先 我们进入这个initial()里面看下他内部是怎么实现的. 2.我们进入里面看到他实现了3个方法,一个认证,权限频率 3.我们首先看下认证组件发生了什么 权限: 啥都没返回,self.per ...

  3. Django Rest Framework(认证、权限、限制访问频率)

    阅读原文Django Rest Framework(认证.权限.限制访问频率) django_rest_framework doc django_redis cache doc

  4. Django Rest framework 之 权限

    django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) django res ...

  5. 04 Django REST Framework 认证、权限和限制

    目前,我们的API对谁可以编辑或删除代码段没有任何限制.我们希望有更高级的行为,以确保: 代码片段始终与创建者相关联. 只有通过身份验证的用户可以创建片段. 只有代码片段的创建者可以更新或删除它. 未 ...

  6. django 之(三) --- 认证|权限

    用户模块 登陆注册1:Django2.0  [ 1:N ] user/url.py from django.urls import path from user.views0 import UserT ...

  7. rest framework 认证 权限 频率

    认证组件 发生位置 APIview 类种的 dispatch 方法执行到 initial 方法 进行 认证组件认证 源码位置 rest_framework.authentication  源码内部需要 ...

  8. Django Rest Framework之权限

    基本代码结构 url.py: from django.conf.urls import url, include from app import views urlpatterns = [ url(r ...

  9. Django REST framework - 认证

    目录 认证 DRF 5种验证方式 如何确定身份验证? 设置身份验证方案 案例: 基于自定义Token认证 第一步: 定义一个用户表和一个保存用户Token的表 第二步: 定义一个登陆视图 第三步定义一 ...

随机推荐

  1. kube-proxy运行机制分析【转载】

    转自:http://blog.itpub.net/28624388/viewspace-2155433/ 1.Service在很多情况下只是一个概念,而真正将Service的作用实现的是kube-pr ...

  2. JWT黑名单和白名单

    单点登录系统 单点登录系统保存了用户的登录名和密码,上网用户在单点登录系统中认证成功后,就可以直接登录各个业务系统. 1. 用户使用单点登录系统的登录界面,输入用户名和密码登录成功后, 单点登录系统为 ...

  3. 38 多线程(十)——volatile 数据同步

    在多线程并发的情况下,同一个变量被多个线程调用,那修改的数据就不会每分每秒保持一致.例如,对于某个变量a,线程1对它进行一套操作,线程2又对它进行另一套操作,但如果cpu太忙了,太忙了,假设cpu都用 ...

  4. int and Integer

    int和Integer的区别 1.Integer是int的包装类,int则是java的一种基本数据类型 2.Integer变量必须实例化后才能使用,而int变量不需要 3.Integer实际是对象的引 ...

  5. IdentityServer4(客户端授权模式)

    1.新建三个项目 IdentityServer:端口5000 IdentityAPI:端口5001 IdentityClient: 2.在IdentityServer项目中添加IdentityServ ...

  6. [洛谷P5340][TJOI2019]大中锋的游乐场

    题目大意:有$n(n\leqslant10^4)$个点,$m(m\leqslant10^5)$条边的无向图,每个点有一个属性$A/B$,要求$|cnt_A-cnt_B|\leqslant k(k\le ...

  7. JNA的应用

    一.了解JNA之前,我们先了解一下JNA的前身JNI(Java Native Interface):通过使用 Java本地接口书写程序,可以确保代码在不同的平台上方便移植. [1]  从Java1.1 ...

  8. vmware的三种网络模式讲解

    vmware有三种网络设置模式,分别是Bridged(桥接),NAT(网络地址转换),Host-only(私有网络共享主机) 1.Bridged(桥接) 桥接模式默认使用的是:VMnet0 什么是桥接 ...

  9. 【CF1095F】 Make It Connected(最小生成树)

    题目链接 如果没有特殊边的话显然答案就是权值最小的点向其他所有点连边. 所以把特殊边和权值最小的点向其他点连的边丢一起跑最小生成树就行了. #include <cstdio> #inclu ...

  10. java 使用GraphQL-关联对象

    GraphQL并不会实现关联查询,数据关联需要程序自己实现 官网首页有介绍获取多个资源只需要一个请求,如想获取用户信息和身份证信息,原来需要先查用户信息,再通过用户id查询身份证信息,而在GraphQ ...