Django用户权限通过Token校验

发布时间 2023-03-28 14:41:55作者: SlookUP
最好是将用户权限验证和Token验证放在Django中间件中,以便对所有视图函数进行校验。
下面是一段示例代码,演示了如何实现中间件来进行用户权限验证和Token验证

middleware.py

from django.contrib.auth import authenticate
from django.http import HttpResponseForbidden
from rest_framework.authtoken.models import Token

class AuthMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        user = authenticate(request=request)

        if user and user.is_active:
            request.user = user
            return self.get_response(request)
        else:
            return HttpResponseForbidden()

class TokenAuthMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if 'HTTP_AUTHORIZATION' in request.META:
            auth_header = request.META['HTTP_AUTHORIZATION']
            auth_token = auth_header.split(' ')[1]
            try:
                token = Token.objects.get(key=auth_token)
                request.user = token.user
            except Token.DoesNotExist:
                pass

        return self.get_response(request)

该示例代码包括以下部分:

  • 实现了AuthMiddleware中间件类,用于用户权限验证。在__call__方法中,使用authenticate函数来验证用户,如果验证成功,将用户信息存储在请求对象中,否则返回HttpResponseForbidden。
  • 实现了TokenAuthMiddleware中间件类,用于Token验证。在__call__方法中,首先检查请求头中是否有Authorization字段,如果有,则获取Token值,并使用Token.objects.get函数查询数据库中是否有匹配的Token。如果找到了Token,则将该Token对应的用户信息存储在请求对象中。
  • 将这两个中间件添加到Django项目的中间件列表中,以便对所有视图函数进行用户权限验证和Token验证。例如,在settings.py文件中添加以下代码:

MIDDLEWARE = [
    # ...
    'path.to.AuthMiddleware',
    'path.to.TokenAuthMiddleware',
    # ...
]

对于Token的存储方式,有以下几种常见的选择:

  1. 数据库存储:将Token保存在数据库中,每次需要验证Token时,从数据库中查询Token并进行验证。这种方式的优点是安全性高,不容易被攻击,而且Token的管理也比较方便。缺点是每次需要验证Token时都要查询数据库,会增加一定的性能开销。
  2. 前端缓存存储:将Token保存在前端缓存中,每次需要验证Token时,直接从前端缓存中读取。这种方式的优点是速度快,不需要每次都查询数据库,而且可以降低服务器的压力。缺点是安全性相对较低,容易被攻击。
  3. 分布式缓存存储:将Token保存在分布式缓存中,每次需要验证Token时,直接从缓存中读取。这种方式结合了前两种方式的优点,安全性较高,速度也比较快,而且可以支持分布式部署。

推荐使用第三种方法

分布式缓存存储可以使用诸如Redis、Memcached等分布式缓存系统来实现
下面以Redis为例,介绍如何实现基于Redis的Token存储

首先需要在Django的settings.py中配置Redis:
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}

SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"

其中,LOCATION为Redis的连接地址,可以根据实际情况进行配置
然后可以使用Django的缓存API来实现Token的存储和读取。例如:
from django.core.cache import cache

# 存储Token
# 可以使用cache.set()方法中的timeout参数来设置过期时间
cache.set("token_key", "token_value",timeout=600)

# 读取Token
token_value = cache.get("token_key")