Django Rest 框架的基于密钥的访问

Posted

技术标签:

【中文标题】Django Rest 框架的基于密钥的访问【英文标题】:Key based access for the Django Rest Framework 【发布时间】:2015-02-02 09:44:51 【问题描述】:

假设获取用户列表的 API 端点是这样的

/api_auth/user/

但我想限制只有拥有 api_key

的人才能访问此列表
 /api_auth/user/?access_key=$omeRandomHash3252532

如何使用 Django Rest Framework 实现这样的访问系统?

我应该使用权限来实现吗?

【问题讨论】:

【参考方案1】:

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 设置,像这样

REST_FRAMEWORK = 'DEFAULT_AUTHENTICATION_CLASSES':( 'my_custom_package.authentication.APIKeyAuthentication', )

现在,上面所做的是检查 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_keyUser .然后get_user_from_api_key 函数将查询APIKey 模型以获取具有提供的api_key 的用户。

更新

如果你想使用 django-rest-framework 权限而不是身份验证,你可以像这样创建一个APIKeyPermission 类:

从 rest_framework 导入权限 类 APIKeyPermission(permissions.BasePermission): def has_permission(self, request, view): api_key = request.GET.get('api_key') 返回 check_permission(api_key, 请求)

check_permission 函数将检查传递的 api_key 是否具有该特定请求的权限。请查看 http://www.django-rest-framework.org/api-guide/permissions/ 上的示例以获取更多信息 - 您可以选择实施 has_object_permission 来实施对象级权限而不是视图级权限。

【讨论】:

感谢您的回答,但我感觉我可能需要使用权限来实现这一点。请检查问题中的编辑。 你指的是django权限还是django-rest-framework权限? 嘿,这行得通。知道如何将它添加到我的所有 APIView 中吗? > 应该放在 authentication.py 模块上并配置 @Serafeim 这个文件在哪里?我找不到它。 @volatil3,没地方,这是你自己添加的模块:)【参考方案2】:

如果您能够在请求中设置标头,则可以使用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)

【讨论】:

感谢您的回答,但我觉得我可能需要使用权限来实现这一点。请检查问题中的编辑。 也许能解释一下为什么“你有感觉”你需要权限? 我不想将此访问机制绑定到特定用户,而是绑定到对 API 的所有请求。 好吧听起来你应该使用权限! 知道如何在所有 APIView 中添加单个自定义权限吗?

以上是关于Django Rest 框架的基于密钥的访问的主要内容,如果未能解决你的问题,请参考以下文章

如何在 django rest 框架中访问获取请求数据

如何从 django rest 框架访问 jwt 令牌到 Angular 前端

在 django rest 框架中访问算术的外键属性

Django rest-framework框架-访问频率控制

在 Django REST 框架中使用 JWT 时,刷新令牌和访问令牌存储在哪里?

Api 密钥和 Django Rest Framework Auth Token