Restframework的认证,权限,限制,分页

2018-08-05 07:51:07来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

1.认证

  流程:请求到达REST framework的时候,会对request进行二次封装,在封装的过程中会对客户端发送过来的request封装进认证,选择,解析等功能。request方法封装完成之后,执行initial方法时,又会再次对客户端的请求执行认证操作,确保请求的合法性

  生命周期:

  发送请求-->Django的wsgi-->中间件-->路由系统_执行CBV的as_view(),就是执行内部的dispath方法-->在执行dispath之前,有版本分析 和 渲染器-->在dispath内,对request封装-->版本-->认证-->权限-->限流-->视图-->如果视图用到缓存( request.data or request.query_params )就用到了 解析器-->视图处理数据,用到了序列化(对数据进行序列化或验证) -->视图返回数据可以用到分页

 自定义认证:

models.py(创建完后自行添加几条数据)

from django.db import models

# 用户信息
class UserInfo(models.Model):
	username = models.CharField(max_length=32, unique=True)
	password = models.CharField(max_length=32)
	# 小整数字段
	type = models.SmallIntegerField(
		choices=((1,"普通用户"),(2,"VIP用户")),
		default=1
	)


# 用户认证
class Token(models.Model):
	token = models.CharField(max_length=32)
	user = models.OneToOneField(to="UserInfo")


# 评论表
class Comment(models.Model):
	content = models.CharField(max_length=128)
	user = models.ForeignKey(to='UserInfo', on_delete=models.CASCADE, default=1) 

url.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'login/$', views.LoginView.as_view()),
]


from rest_framework.routers import DefaultRouter
router = DefaultRouter()
# 注册路由,表示路径comment对应视图函数CommentViewSet
router.register(r'comment', views.CommentViewSet)
urlpatterns += router.urls  

views.py

import time
import hashlib
from app01 import models
from rest_framework.views import APIView
from rest_framework.response import Response
from app01 import app01_serializers     # 自定义的序列化
from rest_framework.viewsets import ModelViewSet

# 生成token函数
def get_token_code(username):
	"""
	根据用户名和时间戳生成用户登陆成功的随机字符串
	:param username:字符串格式的用户名
	:return:字符串格式的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):
	"""
	1. 接收用户发过来(POST)的用户名和密码数据
	2. 校验用户名密码是否正确
		- 成功就返回登陆成功(发Token)
		- 失败就返回错误提示
	"""
	def post(self,request):
		res = {"code":0}
		username = request.data.get("username")
		password = request.data.get("password")
		user_obj = models.UserInfo.objects.filter(
			username=username,
			password=password,
		).first()
		if user_obj:
			token = get_token_code(username)
			# 保存token
			# 如果有记录就更新defaults里传的参数, 没有记录就用defaults里传的参数创建一条数据
			models.Token.objects.update_or_create(defaults={"token": token}, user=user_obj)
			# 将token返回给用户
			res["token"] = token
		else:
			res["token"] = 1
			res["error"] = "用户名或密码错误"
		return 	Response(res)


# 对文章进行增删改查操作
class CommentViewSet(ModelViewSet):
	queryset = models.Comment.objects.all()
	serializer_class = app01_serializers.CommentSerializer

app01_serializers.py(app下创建的py文件)

from app01.models import Comment
from rest_framework import serializers


class CommentSerializer(serializers.ModelSerializer):
	class Meta:
		model = Comment
		fields = "__all__"

 通过在postman上模拟post发送请求登录,如果用户名和密码正确的话,会生成token值,下次该用户再登录时,token的值就会更新

当用户名或密码错误时,抛出异常

上面看是没有什么问题,但是任何用户都能访问评论,如何只让登陆用户查看信息呢?这里我们就需要添加一个认证类

在app01(应用名)目录下创建目录utils,在此目录下创建auth.py,用于放置自定义的认证类

auth.py

from app01 import models
from rest_framework.authentication import BaseAuthentication
# 导入处理REST框架引发的异常的模块
from rest_framework.exceptions import AuthenticationFailed


class MyAuth(BaseAuthentication):
	# 重写BaseAuthentication里的方法
	def authenticate(self, request):
		if request.method in ["POST","PUT",]:
			# 取token值
			token = request.data.get("token")
			# 去数据库查询有没有这个token
			token_obj = models.Token.objects.filter(token=token).first()
			if token_obj:
				# token_obj有2个属性,详见models.py中的Token。
				# return后面的代码,相当于分别赋值。例如a=1,b=2等同于a,b=1,2
				# return多个值,返回一个元组
				# 在rest framework内部会将这两个字段赋值给request,以供后续操作使用
				return token_obj.user, token
			else:
				raise AuthenticationFailed("无效的token")
		else:
			return None, None  

  views.py下的CommentViewSet类:

# app01.utils.auth表示app01目录下的utils下的auth.py
from app01.utils.auth import MyAuth

class CommentViewSet(ModelViewSet):
	queryset = models.Comment.objects.all()
	serializer_class = app01_serializers.CommentSerializer
	authentication_classes = [MyAuth, ]  # 局部使用认证方法MyAuth

 验证:发送一个空的post请求或者错误的post请求

发送正确的post请求:

## 以上只是做了一个局部的认证,对于全局认证:

需要在setting中配置:

REST_FRAMEWORK = {
    # 表示app01-->utils下的auth.py里面的MyAuth类
    "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.auth.MyAuth", ]
}

 这时候CommentViewSet中的authentication_classes就可以注释掉了,效果也是一样的  

2.权限

  自定义我们的权限,如只有让VIP用户才能看的内容

 

3.限制

4.分页

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:python学习笔记

下一篇:面向对象进阶