今天讲认证组件,权限组件、频率组件、
我们先写一个登陆,之前用户在登陆的时候都会带上cokie,session,他会带上用户的信息去访问请求,不用用户每次都输入用户名和密码。
用户在登陆的时候,向用户随机分配一个字符串,用户再次登陆的时候会带着这个字符串进行认证。
先在model里面添加两个表,user表和usertoken表,
class User(models.Model): user = models.CharField(max_length=32) pwd = models.CharField(max_length=32) type = ((1,'VIP'),(2,'SVIP'),(3,'SSVIP')) user_type = models.IntegerField(choices=type) class UserToken(models.Model): user = models.OneToOneField(to='User') token = models.CharField(max_length=128)
login视图函数:
然后就是写认证组件了,
之前我们看过解析器的要在视图类函数中加上 parser_classes = [JSONParser,FormParser,MultiPartParser] 这样一个变量,如果不写这个变量,会去默认的这个变量
同样我们把 authentication_classes = [UserAuth] 这个变量加在 book表的视图类函数中。
我们再把源码走一遍:
APIView中的dispatch方法会重新封装request,
点击去initial:
见到request.user应该想到的是user是一个静态方法。
从重新封装的那个request中找user方法。
点进去之后,
我们可以看一下默认的authenticate方法中是不是返回两个值。这样认证组件的源码就算执行完了。
如果我们不定义 authentication_classes = [UserAuth] 他会从试图类中找 authentication_classes,如果找不到,就去全局的settings中找,再找不到就去默认的settings中找,具体解析看前面的解析器部分。
来看代码:
from app01.models import UserToken from rest_framework.exceptions import AuthenticationFailed class UserAuth(object): def authenticate_header(self,request): pass def authenticate(self,request): token = request.GET.get('token') usertoken = UserToken.objects.filter(token=token).first() if usertoken: return usertoken.user,usertoken.token else: raise AuthenticationFailed('认证失败') # 抛出异常错误
当然,我们定义的 authentication_classes = [UserAuth,UserAuth2] 也可以放多个认证类,如果第一个认证类返回空,就走第二个认证类,知道有返回值。
最后的认证类代码:
权限组件:
同样我们把 permission_classes = [SVIPPermission] 权限变量添加到book表的视图类中,
同样的道理:
来看代码:
class SVIPPermission(object): message = '您没有访问权限!!!' def has_permission(self,request,view): if request.user.user_type >= 2: return True return False
3.频率组件
同样的道理,
我们来写一个每分钟限制访问三次的限制频率。
我们每次访问频率受限制的时候,会提示多少时间后才能继续访问,
from rest_framework.throttling import BaseThrottle VISIT_CODE = {} class VisitThrottle(BaseThrottle): def __init__(self): self.history = None def allow_request(self,request,view): # 拿到用户请求的ip值 remote_addr = request.META.get('REMOTE_ADDR') import time ctime = time.time() # 如果IP值不再VISIT_CODE中,说明用户之前没有访问过, if remote_addr not in VISIT_CODE: VISIT_CODE[remote_addr] = [ctime,] # {‘127.0.0.1’:[11:10:10,]} history = VISIT_CODE[remote_addr] self.history = history # 如果history最后一个和当前时间差值大于60s,就把他删除掉。 while history and ctime - history[-1] > 60: history.pop() if len(history) > 3: return False else: history.insert(0,ctime) return True def wait(self): import time ctime = time.time() # 60 - (当前时间与第一次访问的差值) return 60-(ctime-self.history[-1])
这是我们自己写的每分钟访问三次,这样就写死了。其实rest_framework也帮我们做了这样的频率限制。
需要在全局的settings中配置:
10/d,每天访问10此
10/w,每周访问10次