认证
序言
客户认证客户是不是合理合法登录。
一部分內容在DRF主视图的应用及源代码步骤剖析解读,提议首先看解读主视图的本文 。
应用步骤
认证应用的方式 步骤以下:
- 自定认证类 ,承继
BaseAuthentication
,而且覆写其authenticate
方式 。不承继BaseAuthentication
还可以,但认证类中务必申明authenticate
和authenticate_header
2个方式 。 - 当认证根据后应当回到2个值(一个元组) ,而且第一个会传送给
request.user
这一属性中,第二个值可能传送给request.auth
这一属性中 。 - 假如认证不成功,则抛出异常
APIException
或是AuthenticationFailed
,它会全自动捕捉并回到。 - 当今认证类设定是全局应用還是部分应用。
自定认证类:
进行1、2 、3步,出现异常统一回到
AuthenticationFailed。
import jwt from jwt import exceptions import rest_framework.exceptions as rest_exception from rest_framework.authentication import BaseAuthentication from rest_framework import status from app1.models import Login from libs.TokenManager import SALT class MyAuthentication(BaseAuthentication): def authenticate(self, request): token = request.META.get("HTTP_TOKEN") # 在请求头中设定token值,获得的是HTTP_TOKEN if not token: raise rest_exception.AuthenticationFailed(code=status.HTTP_401_UNAUTHORIZED, detail="请在请求头中设定token值!") try: # 分析token verified_payload = jwt.decode(token, SALT, "HS256") user_id, username = verified_payload["user_id"], verified_payload["username"] user = Login.objects.filter(user=user_id, token=token).first() if user: return user_id, username else: raise rest_exception.AuthenticationFailed(code=status.HTTP_401_UNAUTHORIZED, detail="客户不会有!") except exceptions.ExpiredSignatureError: raise rest_exception.AuthenticationFailed(code=status.HTTP_401_UNAUTHORIZED, detail="token早已无效!") except jwt.DecodeError: raise rest_exception.AuthenticationFailed(code=status.HTTP_401_UNAUTHORIZED, detail="token认证不成功!") except jwt.InvalidTokenError: raise rest_exception.AuthenticationFailed(code=status.HTTP_401_UNAUTHORIZED, detail="token不法!")
第4步:
部分认证:
在一个必须认证的CBV里边 ,加上
authentication_classes类属性。如:
class UserAPIView(GenericAPIView, ListModelMixin): authentication_classes = [MyAuthentication] queryset = User.objects serializer_class = UserSerializer
全局认证:
在
settings.py里边设定:
REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": ["libs.MyAuth.MyAuthentication"] }
在源代码剖析一部分 ,大伙儿可能搞清楚为什么那样设定。
源代码剖析
认证的实行,是产生在
dispatch涵数的全过程中 。
特别注意的是,封裝request的情况下 ,大家的特定的认证类也会一起封裝在新的request里边 。
接下去看一下
get_authenticators的实行。应用目录生成式逐个实例化了每一个authentication_classes里边的认证类。而
authentication_classes载入了大家自定的认证类 。注:
如果是部分认证,那麼便是大家立即给
authentication_classes取值如果是全局认证,那麼便是载入大家
settings中的DEFAULT_AUTHENTICATION_CLASSES配备项。
以后 ,在
initial涵数中,实行了三大认证,在其中就会有认证。
而认证立即实行了
request.user,它实际上是一个被
@property装饰设计的方式 。
接下去的实际操作全是在
rest_framework.request控制模块里边。新封裝的request便是这下边的
Request类的案例。
当沒有
_user属性的情况下,表明还未认证,则会实行
_authenticate()方式
- 认证取得成功 ,回到元组 。
- 认证不成功,实行
_not_authenticated
。
填补
最终,一个难题 ,当配备了全局认证之后 ,以后每一个插口的浏览必须实行认证,而有的托词并不一定认证或是认证的类不一样(如登录插口),应该怎么办呢?
实际上很找邦企 ,全局设定之后并不危害部分设定的起效,由于部分设定的优先超过全局设定,就例如针对登录插口而言 ,大家只必须在登录插口CBV中设定
authentication_classes为空就可以了。如果有独特必须,还可以特定别的认证类 。
class LoginAPIView(APIView): authentication_classes = []