【发布时间】:2015-02-02 09:44:51
【问题描述】:
假设获取用户列表的 API 端点是这样的
/api_auth/user/
但我想限制只有拥有 api_key
的人才能访问此列表 /api_auth/user/?access_key=$omeRandomHash3252532
如何使用 Django Rest Framework 实现这样的访问系统?
我应该使用权限来实现吗?
【问题讨论】:
标签: django django-rest-framework
假设获取用户列表的 API 端点是这样的
/api_auth/user/
但我想限制只有拥有 api_key
的人才能访问此列表 /api_auth/user/?access_key=$omeRandomHash3252532
如何使用 Django Rest Framework 实现这样的访问系统?
我应该使用权限来实现吗?
【问题讨论】:
标签: django django-rest-framework
django-rest-framework 不支持开箱即用,但可以轻松实现:
如果您查看http://www.django-rest-framework.org/api-guide/authentication/,您会看到自定义身份验证方法的示例。基于此,您需要实现以下内容:
从 django.contrib.auth.models 导入用户 从 rest_framework 导入认证 从 rest_framework 导入异常 类 APIKeyAuthentication(authentication.BaseAuthentication): def 身份验证(自我,请求): api_key = request.GET.get('api_key') 如果不是 api_key: 返回无 尝试: 用户 = get_user_from_api_key(api_key) 除了 User.DoesNotExist: raise exceptions.AuthenticationFailed('API KEY 没有用户') 返回(用户,无)APIKeyAuthentication 应该放在 authentication.py 模块上,并在 settings.py 上配置REST_FRAMEWORK 设置,像这样
现在,上面所做的是检查 api_key 参数是否存在(如果不存在,它将返回 None 以检查请求是否可以通过不同的方式进行身份验证——如果您不想检查任何其他身份验证类然后只引发exceptions.AuthenticationFailed 异常,就像我们在下面找不到用户时所做的那样。现在,我们需要实现一个get_user_from_api_key 函数,该函数将从API_KEY 返回一个User 实例。如果与相关的用户传过来的 api_key 找到了就会返回,如果没有就会抛出exceptions.AuthenticationFailedexception。
关于get_user_from_api_key 函数,其实现取决于您的要求。例如,如果您想为每个用户创建一个新的 api 密钥,您应该创建一个 APIKey 模型,该模型将具有一个 api_key CharField 和一个 ForeignKey 到具有此 api_key 的 User .然后get_user_from_api_key 函数将查询APIKey 模型以获取具有提供的api_key 的用户。
更新
如果你想使用 django-rest-framework 权限而不是身份验证,你可以像这样创建一个APIKeyPermission 类:
check_permission 函数将检查传递的 api_key 是否具有该特定请求的权限。请查看 http://www.django-rest-framework.org/api-guide/permissions/ 上的示例以获取更多信息 - 您可以选择实施 has_object_permission 来实施对象级权限而不是视图级权限。
【讨论】:
如果您能够在请求中设置标头,则可以使用Rest Framework's Token Authentication。
否则,如果您需要将其作为GET-paramter 放入URL 中,您可以创建自己的custom authentication class:
from rest_framework.authentication import TokenAuthentication
class MyAuthentication(TokenAuthentication):
def authenticate(self, request):
token = request.GET.get('api-key', None)
if token is None:
return None
return self.authenticate_credentials(token)
【讨论】: