Django restframework 认证

认证是比较通用的功能,基本上大多数系统都需要认证功能,

它的流程如下:

请求进来后,先到dispatch方法,dispatch有个initialize_request方法,它会对Request对象进行封装,包括request, authenticators.
将旧的request封装为新的_request, authenticators则通过get_authenticators()方法获取,get_authenticator()方法获取authentication_class,即返回一个认证类的对象列表。initialize_request之后还有一个inital方法,它调用perform_autentication方法,它执行request.user,取user属性,调用authenticator的authenticate方法,该方法返回一个由user对象,auth组成的元组,如果没通过验证,用户被设置为匿名用户,auth被设置为None

restframework中的认证也是分为局部和全局配置两种,

restframework有三种认证方式:

class SessionAuthentication(BaseAuthentication):
    def enforce_csrf(self, request: Request) -> None: ...

class TokenAuthentication(BaseAuthentication):
    keyword: str = ...
    model: Optional[Type[Model]] = ...
    def get_model(self) -> Type[Model]: ...
    def authenticate_credentials(self, key: str) -> Tuple[Any, Any]: ...

class RemoteUserAuthentication(BaseAuthentication):
    header: str = ...

这里用的TokenAuthentication,即当用户登陆后生成一个token保存到数据库,下次请求来的时候就可以验证token查询是否登陆

class LuffyAuthentication(BaseAuthentication):
    def authenticate(self, request):
        """
        Authenticate the request and return a two-tuple of (user, token).
        """
        token = request.query_params.get('token')
        if not token:
            return (None,None)

        user_object = models.UserInfo.objects.filter(token=token).first()
        if user_object:
            return (user_object,token)
        return (None,None)

如果验证通过即将use对象和token返回,否则返回None,这样在request中即保存了user对象的信息,需要取用时只需要调用request.user属性即可。

多数情况下,验证是需要全局配置的,settings.py

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": ['api.extension.auth.LuffyAuthentication', ],
}

但是,像登陆视图,就是用来登陆的,如果此时也进行验证,将会进入死循环,所以需要将它排除在验证之外,这就需要将login视图中的authentication_class指定为空列表。

class LoginView(APIView):
    """
    登录接口
    """

    authentication_classes = []

    def post(self, request, *args, **kwargs):
        user_object = models.UserInfo.objects.filter(**request.data).first()
        if not user_object:
            return Response('登录失败')
        random_string = str(uuid.uuid4())
        user_object.token = random_string
        user_object.save()
        return Response(random_string)

同样的道理,认证是需要全局使用的功能,所以个别不需要的情况下是使用“排除”的方法,即将其认证类指定为空。

上一篇:Django restframework 版本

下一篇:Linux Nginx 配置