使用Django自带的session和auth应用实现Token认证

Django的session和auth应用配合起来很方便的实现了身份认证和会话管理的功能。

现在我的项目在原有网站基础上需要另外提供一套API,只需要简单的一点拓展就可以在现有session和auth应用基础上实现基于Token的认证。

在自己的app下创建middleware.py文件,写一个自己的class,继承django.contrib.session.middleware模块下的SessionMiddleware类,并且重写process_request方法。

from django.conf import settings
from django.contrib.sessions.middleware import SessionMiddleware

class SessionTokenMiddleware(SessionMiddleware):

    def process_request(self, request):
        # 尝试从请求头中获取 Session Key
        session_key = request.META.get("HTTP_" + getattr(settings, "ACCESS_TOKEN_NAME", "Access-Token").replace("-","_").upper())
        if not session_key:
            super().process_request(request)
        else:
            request.session = self.SessionStore(session_key)

在处理请求时,先尝试从请求头中对应字段获取Token,即Session Key,并通过Session引擎获取Session对象。
如果请求头中没有包含Token字段,则调用父类方法。

最后,在登陆API的view中调用auth模块login方法后,从request中获取Session Key放入到响应体中即可。

这里因为是用了 REST-Framework 的 ViewSet,所以需要通过request.stream获取原始Django的HttpRequest对象。

@list_route(methods=["post"], permission_classes=[permissions.AllowAny])
def login(self, request):
    """
    登陆API

    通过手机号和密码进行登陆验证
    """
    serializer = UserSerializer(data=request.data)
    if serializer.authenticate():
        login(request, serializer.authenticated_user)
        response_data = {
            getattr(settings, "ACCESS_TOKEN_NAME", "Access-Token"): request.stream.session.session_key,
            "Expires": int((time.time() + request.stream.session.get_expiry_age()) * 1000)
        }
        response_data.update(serializer.data)
        return Response(data=response_data, status=status.HTTP_200_OK)
    else:
        logout(request)
        return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST)

发表评论

电子邮件地址不会被公开。