一. 认证

  (你是谁?)

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


自定义Token认证

  第一步 : 建表>>>>

    定义一个用户表和一个保存用户Token的表

class UserInfo(models.Model):
username = models.CharField(max_length=16)
password = models.CharField(max_length=32)
type = models.SmallIntegerField(
choices=((0, '普通用户'), (1, 'VIP用户')),
default=0
) class Token(models.Model):
user = models.OneToOneField(to='UserInfo')
token_code = models.CharField(max_length=128)

  第二步: 定义一个登陆视图 >>>>

from rest_framework.views import APIView
from app2 import models
from rest_framework.response import Response
import hashlib, time def get_random_token(username):
"""
根据用户名和时间戳生成随机token
"""
timestamp = str(time.time())
m = hashlib.md5(bytes(username, encoding="utf-8"))
m.update(bytes(timestamp, encoding="utf-8"))
return m.hexdigest() class LoginView(APIView):
"""
校验用户名是否正确从而生成token的视图
"""
def post(self, request):
res = {"code": 0}
# print(request.data)
username = request.data.get("username")
password = request.data.get("password") user = models.UserInfo.objects.filter(username=username, password=password).first()
if user:
token = get_random_token(username)
models.Token.objects.update_or_create(defaults={"token_code": token}, user=user)
res["token"] = token
else:
res["code"] = 1
res["error"] = "用户名或密码错误"
return Response(res)

  第三步: 定义一个认证类 >>>>

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from app2 import models class MyAuth(BaseAuthentication):
def authenticate(self, request):
# if request.method in ["POST", "PUT", "DELETE"]: # 如果在表单中需要判断请求方式 由于表单是post请求,所以获取token 的方式为 request.data.get("token")
# request.query_params为url中的参数
request_token = request.query_params.get("token", None)
if not request_token:
raise AuthenticationFailed('q.缺少token') token_obj = models.Token.objects.filter(token_code=request_token).first()
if not token_obj:
raise AuthenticationFailed("无效的Token")
# token_obj.user 通过token这张表的对象和user这个关联字段 找到 UserInfo表的对象及当前用户对象
return token_obj.user, request_token # else:
# return None, None

  第四步: 使用认证类 >>>>

    视图级别认证

class CommentViewSet(ModelViewSet):

    queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer
authentication_classes = [MyAuth, ]

    全局级别认证

# 在settings.py中配置
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ]
}

二. 权限

  (你能干什么?) 设置只有VIP才能看到的东西

第一步: 自定义一个权限类

"""
自己动手写一个权限组件
"""
from rest_framework.permissions import BasePermission class MyPermission(BasePermission): message = '只有VIP才能访问' def has_permission(self, request, view):
# 认证类中返回了token_obj.user, request_token
# request.auth 等价于request_token
if not request.auth:
return False
# request.user为当前用户对象
if request.user and request.user.type == 1: # 如果是VIP用户
print("requ", request.user, type(request.user))
return True
else:
return False

第二步: 使用

  视图级别配置

class CommentViewSet(ModelViewSet):

    queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer
authentication_classes = [MyAuth, ]
permission_classes = [MyPermission, ]

  全局级别设置

# 在settings.py中设置rest framework相关配置项
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],
"DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
}

三. 控制

  (你一分钟能干多少次?)**好像有点污~~

第一步: 自定义限制类 >>>>

import time

# from rest_framework.throttling import
visit_record = {} class MyThrottle(object): def __init__(self):
self.history = None def allow_request(self, request, view):
# 拿到当前的请求的ip作为访问记录的 key
ip = request.META.get('REMOTE_ADDR')
# 拿到当前请求的时间戳
now = time.time()
if ip not in visit_record:
visit_record[ip] = []
# 把当前请求的访问记录拿出来保存到一个变量中
history = visit_record[ip]
self.history = history
# 循环访问历史,把超过10秒钟的请求时间去掉
while history and now - history[-1] > 10:
history.pop()
# 此时 history中只保存了最近10秒钟的访问记录
if len(history) >= 3:
return False
else:
# 判断之前有没有访问记录(第一次来)
self.history.insert(0, now)
return True def wait(self):
"""告诉客户端还需等待多久"""
now = time.time()
return self.history[-1] + 10 - now # history = ['9:56:12', '9:56:10', '9:56:09', '9:56:08'] # '9:56:18' - '9:56:12' # history = ['9:56:19', '9:56:18', '9:56:17', '9:56:08'] # 最后一项到期的时间就是下一次允许请求的时间 # 最后一项到期的时间:now - history[-1] > 10 # 最后一项还剩多少时间过期
# history[-1] + 10 - now

第二步: 使用 >>>

  视图中使用

class CommentViewSet(ModelViewSet):

    queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer
throttle_classes = [MyThrottle, ]

  全局中使用

# 在settings.py中设置rest framework相关配置项
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],
"DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
"DEFAULT_THROTTLE_CLASSES": ["app01.utils.MyThrottle", ]
}

其实还可以使用内置限制类

from rest_framework.throttling import SimpleRateThrottle

class VisitThrottle(SimpleRateThrottle):

    scope = "xxx"

    def get_cache_key(self, request, view):
return self.get_ident(request)

  全局配置

# 在settings.py中设置rest framework相关配置项
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],
# "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
"DEFAULT_THROTTLE_CLASSES": ["app01.utils.VisitThrottle", ],
"DEFAULT_THROTTLE_RATES": {
"xxx": "5/m",
}
}

看源码:

  1.认证流程

  2. 权限

最新文章

  1. Spark SQL 之 DataFrame
  2. 【HTML5】 web上的音频
  3. angular-ui-router中的$stateProvider设置
  4. Android搭建junit测环境
  5. 攻城狮在路上(叁)Linux(二十二)--- linux磁盘挂载与卸载 mount umount
  6. CPlus的简单线程的制作
  7. [NYIST32]组合数(状压,枚举,暴力)
  8. svn出错错误
  9. qml+opencv(二),实现人脸检测
  10. asp.net EF6.0中出现未找到具有固定名称“System.Data.SqlClient”的 ADO.NET提供程序的实体框架提供程序解决办法
  11. 用深度学习(DNN)构建推荐系统 - Deep Neural Networks for YouTube Recommendations论文精读
  12. 老帖收藏,留供参考:SpringMvc2.5+Mybatis3.2.7
  13. 剑指offer 10.递归和循环 矩形覆盖
  14. 前端-----JavaScript 初识基础
  15. Robotframework 3- 安装
  16. java高并发编程(三)
  17. Linux 双网卡配置两个IP同时只有一个会通的原因
  18. Python之分支结构
  19. 在 JS 对象中使用 . 和 [] 操作属性的区别
  20. Linux删除多余内核

热门文章

  1. [SharePoint][SharePoint2013循序渐进]SPS2013简介
  2. 由free命令想到的
  3. MySQL DROP TABLE操作以及 DROP 大表时的注意事项
  4. php PDO连接mysql
  5. 虚拟ONVIF 摄像机
  6. Linux系统编程——多线程实现多任务
  7. 常用的Linux 命令
  8. .net mvc Model 验证总结
  9. 2016.02.25,英语,《Vocabulary Builder》Unit 02
  10. 编译Redis系统提示缺少gcc,可以使用yum进行安装: