简体   繁体   English

Api 密钥和 Django Rest Framework 身份验证令牌

[英]Api key and Django Rest Framework Auth Token

I'm already using build-in Django rest auth token and I plan to release an other api that will be called by an external integrations to call some action in my Django application.我已经在使用内置的 Django rest auth 令牌,我计划发布另一个 api,它将被外部集成调用以在我的 Django 应用程序中调用某些操作。 The issue is that I want to generate an other token for this external api call that must be separate from auth system (fi like Mandrill API Keys or Github Personal Access Token).问题是我想为此外部 api 调用生成另一个令牌,该令牌必须与身份验证系统分开(像 Mandrill API 密钥或 Github 个人访问令牌)。 Is it a good solution to generate api keys from Django rest framework authtoken Model ?从 Django rest framework authtoken Model 生成 api 密钥是一个很好的解决方案吗?

External api token:外部api令牌:

  • must never expire (it could expire in a session auth system)绝不能过期(它可能会在会话身份验证系统中过期)
  • could be linked to user but not required (if linked to account)可以链接到用户但不是必需的(如果链接到帐户)
  • could be revoked and reactivated可以撤销和重新激活

Do you have any experience with releasing api keys ?您有发布 api 密钥的经验吗?

Is it any best practice recommended by Django Rest Framework ?这是 Django Rest Framework 推荐的最佳实践吗?

Thank you ;)谢谢;)

I have created a new authentication backend and a new token model to avoid side effect on build-in token behaviour.我创建了一个新的身份验证后端和一个新的令牌模型,以避免对内置令牌行为产生副作用。

models.py模型.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)

Then you can request secured api with:然后您可以使用以下命令请求安全 api:

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

If I understand you correctly, then Json Web Tokens is the solution for your needs.如果我理解正确,那么Json Web Tokens就是满足您需求的解决方案。 There is a really good django package available that integrates smoothly with django rest framework: django-rest-framework-jwt .有一个非常好的 django 包可以与 django rest 框架顺利集成: django-rest-framework-jwt

With this package you can有了这个包,你可以

  1. set the expiration time设置过期时间
  2. reactivate or revoke the key重新激活或撤销密钥
  3. determine from every external call to your api, if the token is valid从对您的 api 的每次外部调用中确定令牌是否有效

Still仍然

Hope that helps.希望有帮助。

The djangorestframework-api-key library may be a better option currently. djangorestframework-api-key库目前可能是更好的选择。

From the docs:从文档:

Django REST Framework API Key is a powerful library for allowing server-side clients to safely use your API. Django REST Framework API Key 是一个强大的库,允许服务器端客户端安全地使用您的 API。 These clients are typically third-party backends and services (ie machines) which do not have a user account but still need to interact with your API in a secure way.这些客户端通常是没有用户帐户但仍需要以安全方式与您的 API 交互的第三方后端和服务(即机器)。

It's a well-supported and simple-to-use way of releasing new API keys manually or programatically for Django REST Framework projects.这是一种支持良好且易于使用的方法,可以手动或以编程方式为 Django REST Framework 项目发布新的 API 密钥。

Simplest integration:最简单的集成:

# 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",
    ]
}

Then you can create new API keys through admin interface or programatically through the rest_framework_api_key.models.APIKey object.然后您可以通过管理界面或通过rest_framework_api_key.models.APIKey对象以编程方式创建新的 API 密钥。

Edit: Tokens can be revoked as well编辑:令牌也可以撤销

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM