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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
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对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@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)

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

https://blog.dennic365.com/2019/03/19/django-session-auth-token/

作者

Dennic

发布于

2019-03-19

更新于

2022-02-24

许可协议

评论