Api密钥和Django Rest Framework Auth Token

时间:2016-03-21 15:25:01

标签: python django authentication django-rest-framework api-key

我已经使用了内置的Django rest auth令牌,我打算发布一个其他的api,它将被外部集成调用,以便在我的Django应用程序中调用一些动作。问题是我想为这个外部api调用生成另一个令牌,该令牌必须与auth系统分开(f.i.如Mandrill API Keys或Github Personal Access Token)。从Django rest框架authtoken Model?

生成api密钥是一个很好的解决方案吗?

外部api令牌:

  • 必须永不过期(可能会在会话身份验证系统中失效)
  • 可以链接到用户但不是必需的(如果链接到帐户)
  • 可以撤销并重新启动

你有发布api密钥的经验吗?

这是Django Rest Framework推荐的最佳做法吗?

谢谢;)

3 个答案:

答案 0 :(得分:9)

我创建了一个新的身份验证后端和一个新的令牌模型,以避免对内置令牌行为产生副作用。

models.py

class ApiKeyToken(models.Model):
    key = models.CharField(max_length=40, primary_key=True)
    company = models.ForeignKey(Company)
    is_active = models.BooleanField(default=True)

    def save(self, *args, **kwargs):
        if not self.key:
            self.key = self.generate_key()
        return super(ApiKeyToken, self).save(*args, **kwargs)

    def generate_key(self):
        return binascii.hexlify(os.urandom(20)).decode()

    def __unicode__(self):
        return self.key

authentication.py

class ApiKeyAuthentication(TokenAuthentication):

    def get_token_from_auth_header(self, auth):
        auth = auth.split()
        if not auth or auth[0].lower() != b'api-key':
            return None

        if len(auth) == 1:
            raise AuthenticationFailed('Invalid token header. No credentials provided.')
        elif len(auth) > 2:
            raise AuthenticationFailed('Invalid token header. Token string should not contain spaces.')

        try:
            return auth[1].decode()
        except UnicodeError:
            raise AuthenticationFailed('Invalid token header. Token string should not contain invalid characters.')

    def authenticate(self, request):
        auth = get_authorization_header(request)
        token = self.get_token_from_auth_header(auth)

        if not token:
            token = request.GET.get('api-key', request.POST.get('api-key', None))

        if token:
            return self.authenticate_credentials(token)

    def authenticate_credentials(self, key):
        try:
            token = ApiKeyToken.objects.get(key=key)
        except ApiKeyToken.DoesNotExist:
            raise AuthenticationFailed('Invalid Api key.')

        if not token.is_active:
            raise AuthenticationFailed('Api key inactive or deleted.')

        user = token.company.users.first()  # what ever you want here
        return (user, token)

然后您可以通过以下方式请求安全api:

curl http://example.com/api/your-awesome-api.json -H "Authorization: Api-Key {token}" 

答案 1 :(得分:2)

如果我理解正确,那么Json Web Tokens就是满足您需求的解决方案。有一个非常好的django包可以与django rest框架顺利集成:django-rest-framework-jwt

使用此套餐,您可以

  1. 设置到期时间
  2. 重新启用或撤消密钥
  3. 从您的api的每次外部呼叫确定,如果令牌有效
  4. 仍然

    希望有所帮助。

答案 2 :(得分:2)

djangorestframework-api-key 库目前可能是更好的选择。

来自文档:

<块引用>

Django REST Framework API Key 是一个强大的库,用于允许 服务器端客户端以安全地使用您的 API。这些客户是 通常是第三方后端和服务(即机器) 没有用户帐户但仍需要与您的 API 进行交互 安全的方式。

这是一种支持良好且易于使用的方法,可以手动或以编程方式为 Django REST Framework 项目发布新的 API 密钥。

最简单的集成:

# settings.py

INSTALLED_APPS = [
  # ...
  "rest_framework",
  "rest_framework_api_key",
]
python manage.py migrate
# settings.py
REST_FRAMEWORK = {
    "DEFAULT_PERMISSION_CLASSES": [
        "rest_framework_api_key.permissions.HasAPIKey",
    ]
}

然后您可以通过管理界面或通过 rest_framework_api_key.models.APIKey 对象以编程方式创建新的 API 密钥。

编辑:令牌也可以撤销