drf 组件认证浅析

170 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

相信只要做过类似有登录功能的,可以毫不避讳的说,认证肯定是功能里面最基础,但是也是最重要的,并且也不能抛弃的。

如果有做过登录功能,但是没有任何认证的,麻烦评论底下留个网址,相信广大网友会给你生动且形象的上一课, 让你了解知道世界的美好,人性的善良,正义的光撒满人间。

好了,言归正传,在这篇文章里面,主要是从这几个方面去进行浅析,去简单分析一下drf中认证的使用:

  1. drf 基础认证
  2. drf 自定义认证
  3. drf Token认证
  4. drf Session认证

1. drf 基础认证

从网页简单的登录请求去一步步的去触发过程。

透过一层层的drf代码,简单的看一下drf组件认证的实现过程,大致的流程图应该如下:

image.png 文字的大概描述应该类似这样子:

  1. 登录的请求,触发请求认证接口进入了APIView类的dispatch方法
  2. dispatch里执行self.initialize_request这个方法,重定义request,并且得到了自己定义的认证类对象
  3. 执行self.initial()方法中的self.perform_authentication, 里面运行了user方法
  4. 执行user方法里面的self._authenticate() 方法
  5. 把认证的信息返回

那么其实基础的认证流程已经走完,用简单的代码实现来说,大概应该是这样子的

class LoginView(APIView):
    def post(self, request, *args, **kwargs):
        data = request.data
        username = data.get("username")
        password = data.get("password")
        user = authenticate(username=username, password=password)
        if user:
            return Response("认证成功")
        else:
            return Response("认证失败", status=500)

2. drf 自定义认证

经过上面基础认证的简单介绍,那么自定义认证其实也是基于上面去进行开发, 大体流程其实不变。

实现自定义身份验证方案,请继承 BaseAuthentication 并重写 .authenticate(self, request) 方法。 如果认证成功,该方法应返回 (user, auth) 的二元组,否则返回 None。

大概代码应该是这样子的

from django.contrib.auth.models import User 
from rest_framework import authentication 
from rest_framework import exceptions 

class ExampleAuthentication(authentication.BaseAuthentication): 
    def authenticate(self, request): 
        username = request.META.get('X_USERNAME') 
        if not username: 
            return None 
        try: 
            user = User.objects.get(username=username) 
        except User.DoesNotExist: 
            raise exceptions.AuthenticationFailed('No such user') 
        return (user, None)

# LoginView引用
class LoginView(APIView):
    def post(self, request, *args, **kwargs):
		...
		user = ExampleAuthentication().authenticate(request)
		

3. drf token认证

drf 中除了基础认证外,还可以搭配使用简单的基于令牌的HTTP认证方案。

基于token 认证流程:用户登录,服务端给返回的token,并将token保存在服务端,以后再来访问时,需要携带token,服务器获取token后,再去数据库中获取token来进行校验

这个使用也很简单方便,配置起来也方便,并且比简单认证更可靠点。

settings.py文件中INSTALLED_APPS 设置 rest_framework.authtoken,全局设置

'DEFAULT_AUTHENTICATION_CLASSES': (
    'rest_framework.authentication.TokenAuthentication',
),

执行数据迁移命令会生成authtoken表,这个表就是用于存放用户的Token值

用户生成Token,一般来说,可以设置用户token值的过期时间 REST_FRAMEWORK_TOKEN_EXPIRE_MINUTES = 60 * 24, 然后在登录的时候判断是否过期。

如果过期了,则重新生成,没有过期则继续使用该token进行验证。

大致的代码如下:

class LoginView(APIView):
    def post(self, request, *args, **kwargs):
        data = request.data
        username = data.get("username")
        password = data.get("password")
        user = authenticate(username=username, password=password)
        if user:
            # 基础认证ok,加上Token
            token = Token.objects.get_or_create(user=user)[0]
            # 用户token有效期验证,_expiring_token_authentication 自己写相应规则
            token = _expiring_token_authentication(token=token, user=user)
            return Response({"code": 200, "data": {"token": token.key, "user_id": user.id}})
        else:
            return Response("认证失败", status=500)
# 其他view
class SearchView(APIView):
    # 视图里面设置
    authentication_classes = [TokenAuthentication]

    def post(self, request, *args, **kwargs):
       pass

4. drf session认证

django 数据迁移的时候也会生成一个django_session的表格,这个表格就是存储这个用户的session数据的。

settings.py 文件全局配置Session认证

'DEFAULT_AUTHENTICATION_CLASSES': (
    'rest_framework.authentication.SessionAuthentication',
),

一般在访问admin后台登录,输入用户名密码的时候,后台会自动生成 session。

71E819BA-271F-49ab-B07F-E3632946D7B5.png 我们透过login这个一步步的去看代码,看到在登录的时候就会通过get_session_auth_hash()获取sessionid 然后把这个sessionid保存在数据库和request.session中。

如果你要自定义session的生成或者其他,那么也可以参考一下源码,然后加入自己的逻辑,进行开发,写一个自己需要的APIView。

结语

截止到这里,该讲的已经讲完了,也希望这些东西能给人一点点作用,当然,文章不是完美的,有缺漏有错的也可以提出来,我也能进一步学习。

最后,如果可以,点赞支持一波也行。