认证
1、主路由表
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('certification/',include('certification.urls')),
]
2、APP的mode
from django.db import models
class UserInfo(models.Model):
user_type = (
(1,'普通用户'),
(2,'vip'),
(3,'svip'),
)
user_type = models.IntegerField(choices=user_type)
u_name = models.CharField(max_length=16,unique=True)
u_password = models.CharField(max_length=64)
class Meta:
db_table = 'student'
def to_dict(self):
return {'id':self.id,'u_name':self.u_name,'u_password':self.u_password,'user_type':self.user_type}
class UserToken(models.Model): #token表
user = models.OneToOneField(to='UserInfo',on_delete=models.CASCADE)
token = models.CharField(max_length=64)
3、APP路由表
from django.urls import path
from certification import views
urlpatterns = [
path('request/', views.CBVget.as_view(), name='request'),
path('lg/',views.CBVlogin.as_view(),name='lg')
]
4、APP的权限认证表
from rest_framework import exceptions
from rest_framework.views import APIView
from certification.models import UserInfo,UserToken
from rest_framework.authentication import BaseAuthentication
class Authtication(BaseAuthentication):
def authenticate(self,request): #做认证逻辑
token = request.query_params.get('token')
token_obj = UserToken.objects.filter(token=token).first()
if not token_obj:
data = {
'code':10001,
'msg':'认证失败'
}
raise exceptions.AuthenticationFailed(data)
return (token_obj.user,token_obj)
def authenticate_header(self,request): #认证失败给浏览器返回的响应头
pass
5、APP的views
from django.http import JsonResponse
from rest_framework.views import APIView #rest_framework需要到setting里面设置
from certification.models import UserInfo,UserToken
import uuid
from certification.utils.auth import Authtication
class CBVget(APIView):
authentication_classes = [Authtication,] #也可以使用全局设置,在setting里面配置REST_FRAMEWORK={}
def get(self,request,*args,**kwargs): #根据权限查询人员信息信息
user_list =UserInfo.objects.all() #all获取的是all返回的是QuerySet对象,程序并没有真的在数据库中执行SQL语句查询数据
# ,但支持迭代,使用for循环可以获取数据。
user_list_json = []
for user in user_list:
user_list_json.append(user.to_dict())
data ={
'code':1000,
'msg':'success',
'data':user_list_json
}
return JsonResponse(data=data)
class CBVlogin(APIView):
def post(self,request,*args,**kwargs): #登录学生信息
ret = {'code':1000,'msg':None}
try:
user = request._request.POST.get('u_name')
pwd = request._request.POST.get('u_password')
obj = UserInfo.objects.filter(u_name=user,u_password=pwd).first() #查找匹配用户
if not obj:
ret['code'] = 1001
ret['msg'] = '用户名或密码错误'
#为用户创建token
# token = uuid(user)
token = uuid.uuid4().hex
#存在就更新,不存在就创建
UserToken.objects.update_or_create(user=obj,defaults={'token':token})
ret['token'] = token
except Exception as e:
ret['code'] = '1002'
ret['msg'] = '请求异常'
return JsonResponse(ret)
认证知识点梳理:
1、使用
创建类:继承BaseAuthentication,实现authenticate方法
返回值:
none:不管,下一个认证来执行
raise exceptions.AuthenticationFailed('用户认证失败')
(元素1,元素2);元素1赋值给request.user,元素2赋值给request.auth
局部使用:from rest_framework.authentication import BaseAuthentication,BasicAuthentication
class UserInfo(APIView):
authentication_classes = [BasicAuthentication]
def get(self,request,*args,**kwargs):
print(request.user)
return HttpResponse('用户信息')
全部使用:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES':['cretification.utils.auth.Authtication'],
'UNAUTHENTICATED_USER':None, #匿名,request.user = None
'UNAUTHENTICATED_TOKEN':None, #匿名 request.auth = None
}
2、源码流程
dispatch
封装request
获取定义的认证类(全局/局部),通过列表生成式创建对象
initial
perform authenticate
request.user (内部循环。。。)
权限
路由配置同上
1、权限表
from rest_framework.permissions import BasePermission
class MyPermission(BasePermission):
message = '只有svip才可以访问' #自定义返回的提示语
def has_permission(self,request,view):
if request.user.user_type != 3:
return False
return True
2、APP的view表
from django.http import JsonResponse
from rest_framework.views import APIView #rest_framework需要到setting里面设置
from certification.utils.auth import Authtication
from certification.utils.permission import MyPermission
class CBVget(APIView):
permission_classes = [MyPermission,] #引用认证
authentication_classes = [Authtication,] #也可以使用全局设置,在setting里面配置REST_FRAMEWORK={}
def get(self,request,*args,**kwargs):
self.dispatch
ret = {'code':2000,'msg':None,'data':None}
try:
return JsonResponse(data=ret)
except Exception as e:
pass
return JsonResponse('查询失败')
使用SVIP用户访问的结果入下:
使用非SVIP用户访问的结果如下:
使用BasePermission实现的权限认证,与注册用户时自动根据用户名配置其权限信息
from django.http import JsonResponse
from rest_framework.views import APIView #rest_framework需要到setting里面设置
from certification.models import UserInfo,UserToken
import uuid
from certification.utils.auth import Authtication
from certification.utils.permission import MyPermission
class CBVget(APIView):
permission_classes = [MyPermission,] #引用认证
authentication_classes = [Authtication,] #也可以使用全局设置,在setting里面配置REST_FRAMEWORK={}
def get(self,request,*args,**kwargs): #根据权限查询人员信息信息
user_list =UserInfo.objects.all() #all获取的是all返回的是QuerySet对象,程序并没有真的在数据库中执行SQL语句查询数据
# # ,但支持迭代,使用for循环可以获取数据。
user_list_json = []
user_token = request.query_params.get('token') #获取用户的token信息
user_id = UserToken.objects.get(token=user_token).user_id #根据token获取user_id
user_type = UserInfo.objects.get(id=user_id).user_type #根据user_id获取用户类型
if user_type == 3:
for user in user_list:
user_list_json.append(user.to_dict())
data ={
'code':2000,
'msg':'success',
'data':user_list_json
}
return JsonResponse(data=data)
else:
user_token = request.query_params.get('token')
user_id = UserToken.objects.get(token=user_token).user_id
user_list = UserInfo.objects.get(id=user_id)
data ={
'code':2000,
'msg':'success',
'data':user_list.to_dict()
}
return JsonResponse(data=data)
class CBVlogin(APIView):
def post(self,request,*args,**kwargs): #登录学生信息
# action = request._request.GET.get('action') #query_params等于_request.GET,进到源码查看
action = request.query_params.get('action')
if action == 'login':
ret = {'code':1000,'msg':None}
try:
user = request._request.POST.get('u_name')
pwd = request._request.POST.get('u_password')
obj = UserInfo.objects.filter(u_name=user,u_password=pwd).first() #查找匹配用户
if not obj:
ret['code'] = 1001
ret['msg'] = '用户名或密码错误'
#为用户创建token
# token = uuid(user)
token = uuid.uuid4().hex
#存在就更新,不存在就创建
UserToken.objects.update_or_create(user=obj,defaults={'token':token})
ret['token'] = token
except Exception as e:
ret['code'] = '1002'
ret['msg'] = '请求异常'
return JsonResponse(ret)
elif action == 'regist': #注册用户,根据用户名直接设置该用户的角色
user_type_svip = ['cq','yyx'] #用户配置表可以放到一块,再引用过来
user_type_vip = ['zjj','lfr']
user = request._request.POST.get('u_name')
pwd = request._request.POST.get('u_password')
users = UserInfo()
users.u_name = user
users.u_password = pwd
print(user,pwd)
if user in user_type_svip:
user_type = 3
users.user_type = user_type
elif user in user_type_vip:
user_type = 2
users.user_type = user_type
else:
user_type = 1
users.user_type = user_type
users.save()
ret = {
'code': 2000,
'msg': '新增用户成功',
}
return JsonResponse(ret)
权限知识点梳理:
1、使用
类:必须继承:BasePermission 必须实现:has_permission方法
返回值:
-True:有权访问
-False:无权访问
局部使用:
permission_classes = [MyPermission,]
def get(self,request,*args,**kwargs):
return HttpResponse('用户信息')
全局配置:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES':['cretification.utils.permission.MyPermission']
}
节流
路由配置同上
1、APP节流表
import time
from rest_framework.throttling import BaseThrottle,SimpleRateThrottle
VISIT_RECORD = {} #设置的全局,重启就没了,可以放到数据库或者缓存
class VisitThrottle(BaseThrottle):
"""60秒内访问3次"""
def __init__(self):
self.history = None
def allow_request(self, request, view):
# 获取用户ip
# ip_addr = self.get_ident(request) #类自带的获取ip的方法
ip_addr = request.META.get('REMOTE_ADDR')
ctime = time.time()
if ip_addr not in VISIT_RECORD:
VISIT_RECORD[ip_addr] = [ctime]
return True
history = VISIT_RECORD.get(ip_addr)
self.history = history
while history and history[-1] < ctime - 60: # 判断历史表里面的第一次访问时间是否超过一分钟
history.pop() # 超多了就删除掉
if len(history) < 3:
history.insert(0, ctime) # 满足条件就可以访问,并把访问时间插入历史列表
return True
# return True #表示可以访问,反之不可以访问
def wait(self):
"""显示还有多少秒可以访问"""
ctime = time.time()
return 60 - (ctime - self.history[-1]) # 得到可以访问的时间
#类自带的实现次数限定,
class VisitThrottle(SimpleRateThrottle):
"""
设置,根据IP限制每分钟访问3次
"""
scope = 'cc' #随意写,源码当做key值调用 需要到配置文件设置
def get_cache_key(self, request, view):
# self.parse_rate() #可以到源码查看,配置文件设置时间和次数的格式
return self.get_ident(request)
2、APP的view
from django.http import JsonResponse
from rest_framework.views import APIView #rest_framework需要到setting里面设置
from certification.models import UserInfo,UserToken
import uuid
from certification.utils.auth import Authtication
from certification.utils.permission import MyPermission
from certification.utils.throttle import VisitThrottle
class CBVget(APIView):
permission_classes = [MyPermission,] #引用认证
authentication_classes = [Authtication,] #也可以使用全局设置,在setting里面配置REST_FRAMEWORK={}
throttle_classes = [VisitThrottle,] #节流
def get(self,request,*args,**kwargs): #根据权限查询人员信息信息
user_list =UserInfo.objects.all() #all获取的是all返回的是QuerySet对象,程序并没有真的在数据库中执行SQL语句查询数据
# # ,但支持迭代,使用for循环可以获取数据。
user_list_json = []
user_token = request.query_params.get('token') #获取用户的token信息
user_id = UserToken.objects.get(token=user_token).user_id #根据token获取user_id
user_type = UserInfo.objects.get(id=user_id).user_type #根据user_id获取用户类型
if user_type == 3:
for user in user_list:
user_list_json.append(user.to_dict())
data ={
'code':2000,
'msg':'success',
'data':user_list_json
}
return JsonResponse(data=data)
else:
user_token = request.query_params.get('token')
user_id = UserToken.objects.get(token=user_token).user_id
user_list = UserInfo.objects.get(id=user_id)
data ={
'code':2000,
'msg':'success',
'data':user_list.to_dict()
}
return JsonResponse(data=data)
class CBVlogin(APIView):
def post(self,request,*args,**kwargs): #登录学生信息
# action = request._request.GET.get('action') #query_params等于_request.GET,进到源码查看
action = request.query_params.get('action')
if action == 'login':
ret = {'code':1000,'msg':None}
try:
user = request._request.POST.get('u_name')
pwd = request._request.POST.get('u_password')
obj = UserInfo.objects.filter(u_name=user,u_password=pwd).first() #查找匹配用户
if not obj:
ret['code'] = 1001
ret['msg'] = '用户名或密码错误'
#为用户创建token
# token = uuid(user)
token = uuid.uuid4().hex
#存在就更新,不存在就创建
UserToken.objects.update_or_create(user=obj,defaults={'token':token})
ret['token'] = token
except Exception as e:
ret['code'] = '1002'
ret['msg'] = '请求异常'
return JsonResponse(ret)
elif action == 'regist': #注册用户,根据用户名直接设置该用户的角色
user_type_svip = ['cq','yyx'] #用户配置表可以放到一块,再引用过来
user_type_vip = ['zjj','lfr']
user = request._request.POST.get('u_name')
pwd = request._request.POST.get('u_password')
users = UserInfo()
users.u_name = user
users.u_password = pwd
print(user,pwd)
if user in user_type_svip:
user_type = 3
users.user_type = user_type
elif user in user_type_vip:
user_type = 2
users.user_type = user_type
else:
user_type = 1
users.user_type = user_type
users.save()
ret = {
'code': 2000,
'msg': '新增用户成功',
}
return JsonResponse(ret)
超时的效果图
知识点梳理:
1、基本使用
类:继承BaseThrottle ,实现:allow_request wait
类: 继承SimpleRateThrottle 实现:get_cache_key scope = 'cc' ==>配置文件中的key
2、局部
throttle_classes = [VisitThrottle,] #节流
3、全局
REST_FRAMEWORK = {
'DEFAULT_THROTTL_RATES':{
'cc':"3/m" #代码每一分钟访问3次,具体可以进到源码parse_rate查看设置方式
},
}