Django REST Framework API Key如何按API密钥设置视图/端点权限
DRF API Key 按密钥分配路由权限实现方案
核心逻辑是给每个API Key绑定可访问的路由白名单,通过自定义DRF权限类在请求进入视图前完成匹配校验,不匹配直接返回403。
1. 扩展API Key模型存储权限配置
默认的API Key模型没有存储路由权限的字段,需要自定义模型继承官方抽象类扩展字段:
在你的业务app的models.py中添加如下代码:
from django.db import models from rest_framework_api_key.models import AbstractAPIKey class AppAPIKey(AbstractAPIKey): # 存储允许访问的路由前缀列表,例:["/a/", "/c/"] allowed_routes = models.JSONField( default=list, verbose_name="允许访问的路由前缀" )
在项目settings.py中指定使用自定义的API Key模型:
REST_FRAMEWORK_API_KEY = { "API_KEY_MODEL": "你的业务app名.AppAPIKey" }
执行迁移命令生成对应数据表:
python manage.py makemigrations python manage.py migrate
2. 编写自定义路由权限校验类
在业务app下新建permissions.py,实现权限判断逻辑:
from rest_framework.permissions import BasePermission from rest_framework.exceptions import PermissionDenied class HasRouteAccessByAPIKey(BasePermission): def has_permission(self, request, view): # 校验请求是否携带有效API Key api_key = getattr(request, "auth", None) if not api_key or not hasattr(api_key, "allowed_routes"): raise PermissionDenied("无效的API密钥") current_path = request.path_info # 匹配当前请求路径是否在密钥允许的前缀列表中 for route_prefix in api_key.allowed_routes: if current_path.startswith(route_prefix): return True raise PermissionDenied("当前密钥无该接口访问权限")
3. 配置生效并分配密钥权限
首先在DRF配置中注册认证类和权限类,可全局配置也可针对单个视图配置:
全局配置示例(settings.py)
REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": [ "rest_framework_api_key.authentication.APIKeyAuthentication", # 可保留你原有其他认证类,比如SessionAuthentication ], "DEFAULT_PERMISSION_CLASSES": [ "你的业务app名.permissions.HasRouteAccessByAPIKey", ] }
单视图配置示例
如果不需要全局管控,可直接在需要校验的视图类上指定权限类:
from rest_framework.views import APIView from .permissions import HasRouteAccessByAPIKey class AView(APIView): permission_classes = [HasRouteAccessByAPIKey] # 你的视图逻辑
配置完成后,在admin后台创建/编辑三个API Key,分别设置allowed_routes字段值即可:
- apikey1:值设为
["/a/"],仅能访问a/下所有接口 - apikey2:值设为
["/c/"],仅能访问c/下所有接口 - apikey3:值设为
["/a/", "/c/"],可访问a/、c/下所有接口 - 所有Key的允许列表中不添加
/b/前缀,即可实现所有密钥均无法访问b/路由的需求
注意事项
- 路由前缀必须带前后斜杠,比如写
/a/不要写a,避免出现/ab/这类路径被误匹配到/a/规则的问题 - 如果需要区分请求方法做更细粒度控制,可以调整
allowed_routes的存储结构,比如存为[{"path": "/a/", "methods": ["GET", "POST"]}],在权限类中增加request.method的比对逻辑即可 - 如果之前已经使用过默认的API Key模型生成过数据,切换自定义模型后需要重新生成对应密钥,或提前导出旧数据做迁移适配
内容的提问来源于stack exchange,提问作者braulio bracamonte
相关产品推荐
相关产品推荐

