赞
踩
django 3.2.13
解释:认证有五大认证类: BasicAuthentication 、SessionAuthentication 、TokenAuthentication 、RemoteUserAuthentication,他们都继承了BaseAuthentication
认证流程代码:
1. 先通过分发进入认证环节 def dispatch(self, request, *args, **kwargs):[rest_framework.views.py大约485行前后]
2. 先通过request = self.initialize_request(request, *args, **kwargs)来获得一个新的request,里面已经读取过了配置信息,知道下面要用什么认证方式
3. 该函数里面self.initial(request, *args, **kwargs)进入认证、权限、限流功能
4. initial里面的self.perform_authentication(request)进行认证
5. perform_authentication实际调用user()[rest_framework.requests.py大约220行前后]
6. 由user里面的_authenticate进入到user_auth_tuple = authenticator.authenticate(self)这里开始的authenticate[rest_framework.authentication.py]开始根据配置选择认证方式
使用方法:
解释:如果配置全局就无需专门写入局部配置,同理配置局部无需专门写入全局,理由(django在APIView父类里面默认会读取全局配置的,如果局部写相当于覆盖全局配置)
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication', # Basic认证
'rest_framework.authentication.SessionAuthentication', # session认证
'rest_framework.authentication.TokenAuthentication', # session认证
'rest_framework.authentication.RemoteUserAuthentication', # session认证
)
}
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
class TestGenericAPIView(ModelViewSet):
authentication_classes = (SessionAuthentication, BasicAuthentication) # 写在这里
queryset = Student.objects.all()
serializer_class = StudentSerializer
认证方式原理:这种方式不需要Cookie和Session,只需要客户端发起请求的时候,在头部Header中提交用户名和密码(base64格式加密)。如果没有附加,会弹出一个对话框,要求输入用户名和密码。但是它不提供信息加密措施,通常都是以base64编码传输。
好处:简单,不需要Cookie和Session,被广泛支持,一般用于内网比如路由器验证之类
缺点:不安全,不能保存信息,关闭浏览器即失效,不能自己退出,比较落后,信息很容易被篡改,目前并不是特别推荐使用
源码简单分析:
# 承接上面最初的第5步,开始根据配置选择认证方式
1. 认证方式[rest_framework.authentication.py]的BasicAuthentication的authenticate()函数
2. 在authenticate()里面调用auth = get_authorization_header(request).split()
3. get_authorization_header()开始去获取header传来关于名称和密码的md5数据
4. 在下面return self.authenticate_credentials(userid, password, request)[大约87行]调用self.authenticate_credentials()
5. 其中这个函数里面的authenticate()[大约98行]开始查询数据库验证密码
配置:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
],
}
session和cookie:cookie是储存在用户端即浏览器里面,session储存在服务器里面,cookie因为在用户端所以安全差,而且储存内容少,所以把关键内容写入到服务器专门创建的session表里面。当用户第一次请求,服务器就会在session表单里面写入(多个浏览器一个用户,算多次请求,过期或者退出,session可能会消失[依据不同处理逻辑来定]),之后每次请求都会验证是否第一次请求,如果不是则服务器会确定用户操作
认证方式原理:比如用户登录之类都是用其来实现,其是通过验证用户登录后服务器发送给session表单新创建的id号写入cookie(里面有字段为),请求时携带着cookie,提取到服务器去获取cookie里面session的id然后去找到服务器里面的session表去获取里面储存的信息,获取用户身份信息进行验证。Django默认是这种方式
优点:cookie能长期保存,能退出,自主加密比较安全
缺点:cookie不能跨域,服务器数据库保存cookie数据,用户多,服务器储存session压力压力大
源码简单分析:
# 承接上面最初的第5步,开始根据配置选择认证方式
1. 通过user = getattr(request._request, 'user', None)获取request._request属性
2. user属性相当于去获取requests.user这个方法相当于去读取cookie解密session并且去数据库里面提取出,当前的用户。
介绍:未来再介绍
介绍:未来再介绍
基础认证类:
使用方法:
解释:如果配置全局就无需专门写入局部配置,同理配置局部无需专门写入全局,理由(django在APIView父类里面默认会读取全局配置的,如果局部写相当于覆盖全局配置)
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
class TestGenericAPIView(ModelViewSet):
authentication_classes = (SessionAuthentication, ) # 认证方法选择
permission_classes = (IsAuthenticated,) # 关键在这
queryset = Student.objects.all()
serializer_class = StudentSerializer
自定义权限:
导入:from rest_framework.permissions import BasePermission
解释:需要继承BasePermission,并重写has_permission'或者False
和has_object_permission
两个方法即可
区别:has_permission 是用户可以对这个视图有没有 GET POST等权限进行区分,has_object_permission 是 has_permission返回True后,再判断这个用户有没有对一个具体的对象有没有操作权限
class IsOwnerOrReadOnly(BasePermission):
def has_permission(self, request, view):
if request.method =="DELETE":
return True
elif request.method =="GET":
return True
else:
return False
def has_object_permission(self, request, view, obj):
return False
注意:关于has_object_permission()
没有执行,通过翻看源码。①通过继承ModelViewSet类(里面又继承CreateModelMixin、UpdateModelMixin等等这些类,不知道看上篇文章),UpdateModelMixin、RetrieveModelMixin、DestroyModelMixin这三个类(做数据库变动操作和单一查询操作),其会在每次执行前调用self.get_object()
该方法用来检查其是否存在,以及是否有操作权限(这就是关键),其在里面调用 self.check_object_permissions(self.request, obj)
,check_object_permissions又调用自己写的has_object_permission
;②自己写修改、删除、单一查询要调用self.get_object()
该方法,下面展示一段UpdateModelMixin的源代码方便学习self.get_object怎么用
class RetrieveModelMixin:
"""
Retrieve a model instance.
"""
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)
缺陷: 部署到服务器之后,因为启动多个uwsgi进程,所以可能会导致一个进程一段缓存,也就是说,下面的限制会不起效(因为下面的限流基于缓存,不同的进程不一样的缓存)
基础限制类:
AnonRateThrottle 限制未登录用户
UserRateThrottle 限制登录用户
ScopedRateThrottle 具体视图限制
使用方法:
解释:如果配置全局就无需专门写入局部配置,同理配置局部无需专门写入全局,理由(django在APIView父类里面默认会读取全局配置的,如果局部写相当于覆盖全局配置)
导入:from rest_framework.throttling import UserRateThrottle
# 当使用登录与未登录限制的时候,所有视图的访问都会被记录在内
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
),
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day', # 未登录用户一天访问最多100次,anon是默认的
'user': '1000/day'# 登录用户一天访问最多1000次
} # 可以使用 second, minute, hour 或day来指明周期
}
class TestGenericAPIView(ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentSerializer
throttle_classes = (UserRateThrottle,) # 关键
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.ScopedRateThrottle', # 让其靠上先生效
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle',
),
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day', # 未登录用户一天访问最多100次,anon是默认的
'user': '10/hour', # 登录用户一天访问最多1000次
'do':'3/hour' # 关键
},
}
class TestGenericAPIView(ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentSerializer
throttle_classes = (UserRateThrottle,) # 不加默认也有主要靠setting.py里面
throttle_scope = 'do' # 单独视图限流关键
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。