本篇随笔在 "Django REST framework 初识" 基础上扩展

一、认证组件

# models.py
class Account(models.Model):
"""用户表"""
username = models.CharField(verbose_name="用户名", max_length=, unique=True)
password = models.CharField(verbose_name="密码", max_length=) class UserToken(models.Model):
"""用户Token表"""
user = models.OneToOneField(to="Account")
token = models.CharField(max_length=, unique=True)

当然也可以使用django自带的 auth_user 表来保存用户信息,Token表一对一关联这张表或者继承这张表:

from django.contrib.auth.models import User
class Token(models.Model):
user = models.OneToOneField(User)
token = models.CharField(max_length=64) from django.contrib.auth.models import AbstractUser
class Token(AbstractUser):
token = models.CharField(max_length=64)

auth.py

from rest_framework import authentication
from rest_framework import exceptions
from api import models class UserTokenAuth(authentication.BaseAuthentication):
"""用户身份认证"""
def authenticate(self, request):
token = request.query_params.get("token")
obj = models.UserToken.objects.filter(token=token).first()
if not obj:
raise exceptions.AuthenticationFailed({"code": 200, "error": "用户身份认证失败!"})
else:
return (obj.user.username, obj)

Views.py

import time
import hashlib
from rest_framework import viewsets
from rest_framework.views import APIView
from rest_framework.response import Response
from django.core.exceptions import ObjectDoesNotExist
from api import models
from appxx import serializers
from appxx.auth.auth import UserTokenAuth class LoginView(APIView):
"""
用户认证接口
"""
def post(self, request, *args, **kwargs):
rep = {"code": 1000}
username = request.data.get("username")
password = request.data.get("password")
try:
user = models.Account.objects.get(username=username, password=password)
token = self.get_token(user.password)
rep["token"] = token
models.UserToken.objects.update_or_create(user=user, defaults={"token": token})
except ObjectDoesNotExist as e:
rep["code"] = 1001
rep["error"] = "用户名或密码错误"
except Exception as e:
rep["code"] = 1002
rep["error"] = "发生错误,请重试"
return Response(rep) @staticmethod
def get_token(password):
timestamp = str(time.time())
md5 = hashlib.md5(bytes(password, encoding="utf-8"))
md5.update(bytes(timestamp, encoding="utf-8"))
return md5.hexdigest() class BookViewSet(viewsets.ModelViewSet):
authentication_classes = [utils.AuthToken]
queryset = models.Book.objects.all()
serializer_class = serializers.BookSerializer

urls.py

from django.conf.urls import url, include
from rest_framework.routers import DefaultRouter
from appxx import views router = DefaultRouter()
router.register(r"books", views.BookViewSet)
router.register(r"publishers", views.PublisherViewSet) urlpatterns = [
url(r"^login/$", views.LoginView.as_view(), name="login"),
url(r"", include(router.urls)),
]

局部认证(哪个视图类需要认证就在哪加上)

如果需要每条URL都加上身份认证,那么是不是views.py中每个对应的类视图都加上authentication_classes呢?那多麻烦,有没有更简便的方法?请看下面如何设置全局的认证。

全局认证

在settings.py中设置:

REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ["appxx.utils.TokenAuthentication",],
# "UNAUTHENTICATED_USER": None, # 匿名,request.user = None
# "UNAUTHENTICATED_TOKEN": None, # 匿名,request.auth = None
}

可以看到,AuthToken 就是 BookViewSet 用到的 authentication_classes,这样views.py中的每个类视图都不需要加 authentication_classes 了;每条URL都必须经过此认证才能访问。

class BookViewSet(viewsets.ModelViewSet):
queryset = models.Book.objects.all()
serializer_class = serializers.BookSerializer class PublisherViewSet(viewsets.ModelViewSet):
queryset = models.Publisher.objects.all()
serializer_class = serializers.PublisherSerializer

二、权限组件

修改模型表,给用户加上用户类型字段:

class UserProfile(models.Model):
username = models.CharField(verbose_name="用户名", max_length=16)
password = models.CharField(verbose_name="密码", max_length=64)
user_type_choices = ((1, "管理员"), (2, "普通用户"), (3, "VIP"))
user_type = models.SmallIntegerField(choices=user_type_choices, default=2)
class UserTypePermission(permissions.BasePermission):
"""权限认证"""
message = "只有管理员才能访问" def has_permission(self, request, view):
user = request.user
try:
user_type = models.UserProfile.objects.filter(username=user).first().user_type
except AttributeError:
return False
if user_type == 1:
return True
else:
return False

局部权限

class BookViewSet(viewsets.ModelViewSet):
permission_classes = [utils.UserTypePermission]
queryset = models.Book.objects.all()
serializer_class = serializers.BookSerializer

全局权限

REST_FRAMEWORK = {"DEFAULT_PERMISSION_CLASSES": ["appxx.utils.UserTypePermission",],
}

三、访问频率组件

import time

visit_record = {}  # 可以放在redis中
class IpRateThrottle(object):
"""60s内只能访问3次"""
def __init__(self):
self.history = None def allow_request(self, request, view):
ip = request.META.get("REMOTE_ADDR") # 获取用户IP
current_time = time.time()
if ip not in visit_record: # 用户第一次访问
visit_record[ip] = [current_time]
return True history = visit_record.get(ip)
self.history = history while history and history[-1] < current_time - 60:
history.pop() if len(history) < 3:
history.insert(0, current_time)
return True
# return True # 表示可以继续访问
# return False # 表示访问频率太高,被限制 def wait(self):
"""还需要等多久才能访问"""
current_time = time.time()
return 60 - (current_time - self.history[-1])

局部节流

class BookViewSet(viewsets.ModelViewSet):
throttle_classes = [IpRateThrottle]
queryset = models.Book.objects.all()
serializer_class = serializers.BookSerializer

全局节流

REST_FRAMEWORK = {
"DEFAULT_THROTTLE_CLASSES": ["appxx.utils.IpRateThrottle",],
}

PS:

匿名用户:无法控制,因为用户可以换代理IP
登录用户:如果有很多账号,也无法限制

Django REST framework 自定义(认证、权限、访问频率)组件的更多相关文章

  1. Django REST framework 之 认证 权限 限制

    认证是确定你是谁 权限是指你有没有访问这个接口的权限 限制主要是指限制你的访问频率 认证 REST framework 提供了一些开箱即用的身份验证方案,并且还允许你实现自定义方案. 接下类我们就自己 ...

  2. Django Rest framework 之 认证

    django rest framework 官网 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest fra ...

  3. django rest framework用户认证

    django rest framework用户认证 进入rest framework的Apiview @classmethod def as_view(cls, **initkwargs): &quo ...

  4. Django rest framework 的认证流程(源码分析)

    一.基本流程举例: urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^users/', views.HostView.as_view() ...

  5. rest-framework框架——认证、权限、频率组件

    一.rest-framework登录验证 1.models.py添加User和Token模型 class User(models.Model): name = models.CharField(max ...

  6. Rest_Framework之认证、权限、频率组件源码剖析

    一:使用RestFramwork,定义一个视图 from rest_framework.viewsets import ModelViewSet class BookView(ModelViewSet ...

  7. DRF Django REST framework 之 认证组件(五)

    引言 很久很久以前,Web站点只是作为浏览服务器资源(数据)和其他资源的工具,甚少有什么用户交互之类的烦人的事情需要处理,所以,Web站点的开发这根本不关心什么人在什么时候访问了什么资源,不需要记录任 ...

  8. DRF 认证 权限 视图 频率

    认证组件 使用:写一个认证类,继承BaseAuthentication 在类中写authenticate方法,把request对象传入 能从request对象中取出用户携带的token根据token判 ...

  9. restframework 认证、权限、频率组件

    一.认证 1.表的关系 class User(models.Model): name = models.CharField(max_length=32) pwd = models.CharField( ...

随机推荐

  1. 使用 Pascal 脚本编写网页, PWP 项目

    下载后得到 pwp.rar 文件. 解压到一个文件夹里面, 比方  e:\my_sys 文件夹下. 设计一下的脚本. 測试能否够执行. <%  uses sysutils; begin      ...

  2. 箭头函数的 this

    在非严格模式下,匿名函数和定时器中的 this 由于没有默认的宿主对象,因此指向 window: 而在严格模式下,匿名函数和定时器中的 this 由于没有默认的宿主对象,因此为 undefined. ...

  3. [LeetCode][Java] Trapping Rain Water

    题意: Given n non-negative integers representing an elevation map where the width of each bar is 1, co ...

  4. mp3播放时间

    import os os_sep = os.sep this_file_abspath = os.path.abspath(__file__) this_file_dirname, this_file ...

  5. RxJava使用介绍

    主讲人:阳石柏 RxJava基本概念 背压概念介绍 RxJava 2.0版本介绍及更新 一.RxJava基本概念 RxJava 在 GitHub 主页上的自我介绍是 “a library for co ...

  6. UVA 1640(DFS)

    题意:给你a,b两个数 问你a b区间中0 9出现的次数 其实就是求1-n中0-9出现的次数 ans[n]   答案就是ans[b]-ans[a-1] 怎么求的话看代码吧 #include<io ...

  7. SmartDispatcher 类

    UI线程中使用 public class SmartDispatcher { public static void BeginInvoke(Action action) { if (Deploymen ...

  8. PCB genesis连孔加除毛刺孔(圆孔与槽孔)实现方法(二)

    一.为什么 连孔加除毛刺孔 原因是 PCB板材中含有玻璃纤维, 毛刺产生位置在于2个孔相交位置,由于此处钻刀受力不均导致纤维切削不断形成毛刺 ,为了解决这个问题:在钻完2个连孔后,在相交处再钻一个孔, ...

  9. PCB 规则引擎之脚本语言JavaScript应用评测

    世界上没有好做的软件,觉得好做,只是你的系统简单而已,而不是哪个行业简单,特别像我们PCB制造企业务逻辑的很复杂的,仅仅靠决策树中的每个节点布置决策逻辑是不能满足要求的,所以我们在制作PCB规则引擎必 ...

  10. 微信小程序调用微信支付

    1,首先我们先缕清支付的整个流程,详见https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_4&index=3,第一 ...