认证确定了你是谁
权限确定你能不能访问某个接⼝
限制确定你访问某个接⼝的频率
认证
自定义认证类
MyAuthentications.py
实现⾃定义的认证⽅案,要继承BaseAuthentication类并且重写.authenticate(self, request) ⽅法。如果认证成功,该⽅法应返回(user, auth)的⼆元元组,否则返回None。
不管是全局认证还是局部认证,都要使用到自定义认证类。
App\MyAuthentications.py
import itsdangerous
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from App.models import User
from App.util import token_confirm
class MyAuthentaion(BaseAuthentication):
# 自定义的认证类必须实现authenticate,
# 认证的规则,自己定义,成功返回一个二元组(user,value)
def authenticate(self, request):
# 1.获取token
# token可以从请求的get参数中获取
token = request.query_params.get('token')
try:
uid = token_confirm.confirm_validate_token(token,expiration=3600) # expiration=3600 token3600秒之后过期
except itsdangerous.exc.SignatureExpired as e: # token过期
print(e)
raise AuthenticationFailed("token过期")
except:
return None # 认证不成功
# 如果获取到uid
# 查询数据库,获取用户信息
try:
user = User.objects.get(pk=uid)
except:
print("数据库访问错误")
return None
# print(user.__dict__)
print("认证通过")
# 如果找到了用户,认证成功
return (user, None)
util.py
实现token的生成、验证、移除等操作。
from itsdangerous import URLSafeTimedSerializer as utsr
import base64
class Token:
def __init__(self, security_key):
self.security_key = security_key
self.salt = base64.encodebytes(security_key.encode('utf8'))
# 生成token
def generate_validate_token(self, username):
serializer = utsr(self.security_key)
res = serializer.dumps(username, self.salt)
print(serializer)
return res
# 验证token
def confirm_validate_token(self, token, expiration=3600):
serializer = utsr(self.security_key)
return serializer.loads(token, salt=self.salt, max_age=expiration)
# 移除token
def remove_validate_token(self, token):
serializer = utsr(self.security_key)
print(serializer.loads(token, salt=self.salt))
return serializer.loads(token, salt=self.salt)
token_confirm = Token("sdkfksdfkl*(()872873784387#@#@94.,.,xcv,ksdkfi$#$#") # 定义为全局变量
全局认证
- setting设置
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'App.authentications.MyAuthentication',
)
}
- 视图函数获取token
获取的token是所有的user公用的token
views.py
class UserToken(GenericAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
def get(self,request):
# 产生token
user = User.objects.first()
# 使用用户id生成token
token = token_confirm.generate_validate_token(user.id)
# 把token返回给客户端
return Response({'token':token})
path('user/<int:pk>/',views.UserInfoView.as_view(),name='user'),
path('token/',views.UserToken.as_view(),name='usertoken'),
局部认证
- 在视图函数中写认证函数
views.py
class UserInfoView(GenericAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
# 局部认证,只针对当前类
authentication_classes = (MyAuthentaion,)
lookup_field = 'pk'
def get(self,request,pk):
obj = self.get_object() # 获取对象
us = UserSerializer(instance=obj) # 序列化
return Response(us.data)
权限控制
权限控制可以限制⽤户对于视图的访问和对于具体数据对象的访问。
- 在执行视图的dispatch()⽅法前,会先进行视图访问权限的判断。
- 在通过get_object()获取具体对象时,会进行对象访问权限的判断
权限针对模型或者视图对象
全局权限控制
- 在setting中设置DEFAULT_PERMISSION_CLASSES
- 限制访问
最简单的权限是允许通过身份验证的用户访问,并拒绝未经身份验证的用户访问。这对应于 REST framework 中的 IsAuthenticated 类。
稍微宽松的权限会允许通过身份验证的用户完全访问,而未通过身份验证的用户只能进行只读访问。这对应于 REST framework 中的 IsAuthenticatedOrReadOnly 类。
AllowAny 允许所有用户
IsAuthenticated 仅通过认证的用户
IsAdminUser 仅管理员用户
IsAuthenticatedOrReadOnly 认证的用户可以完全操作,否则只能get读取
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
- 无限制访问
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
)
自定义权限控制
App\MyPerssions.py
class MyPermisson(BasePermission):
# 对视图授权
def has_permission(self, request, view):
print("权限限制")
# 返回True就是有权限
# 返回False就是没权限
# return False
# 认证通过就有权限
return request.user and isinstance(request.user,User)
views.py
class UserInfoView(GenericAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
# 局部认证,只针对当前类
authentication_classes = (MyAuthentaion,)
# 授权
permission_classes = (MyPermisson,)
lookup_field = 'pk'
def get(self,request,pk):
obj = self.get_object() # 获取对象
us = UserSerializer(instance=obj) # 序列化
return Response(us.data)