Python Api密钥和Django Rest框架身份验证令牌

Python Api密钥和Django Rest框架身份验证令牌,python,django,authentication,django-rest-framework,api-key,Python,Django,Authentication,Django Rest Framework,Api Key,我已经在使用内置的Django rest auth令牌,我计划发布一个其他api,外部集成将调用该api来调用Django应用程序中的某些操作。问题是,我想为这个外部api调用生成另一个令牌,该令牌必须与auth系统分开(f.I.,如Mandrill api密钥或Github个人访问令牌)。从Django rest框架authtokenModel生成api密钥是一个好的解决方案吗 外部api令牌: 必须永不过期(它可能在会话身份验证系统中过期) 可以链接到用户,但不是必需的(如果链接到帐户)

我已经在使用内置的Django rest auth令牌,我计划发布一个其他api,外部集成将调用该api来调用Django应用程序中的某些操作。问题是,我想为这个外部api调用生成另一个令牌,该令牌必须与auth系统分开(f.I.,如Mandrill api密钥或Github个人访问令牌)。从Django rest框架
authtoken
Model生成api密钥是一个好的解决方案吗

外部api令牌:

  • 必须永不过期(它可能在会话身份验证系统中过期)
  • 可以链接到用户,但不是必需的(如果链接到帐户)
  • 可以被撤销和重新激活
您是否有发布api密钥的经验

这是Django Rest框架推荐的最佳实践吗


谢谢;)

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

有了这个包裹,你可以

  • 设置过期时间
  • 重新激活或撤销密钥
  • 通过对api的每次外部调用确定令牌是否有效
  • 仍然


    希望能有所帮助。

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

    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
    
    身份验证.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}" 
    
    目前,图书馆可能是一个更好的选择

    从文档中:

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

    对于Django REST框架项目,这是一种支持良好且易于使用的手动或编程发布新API键的方法

    最简单的集成:

    # settings.py
    
    INSTALLED_APPS = [
      # ...
      "rest_framework",
      "rest_framework_api_key",
    ]
    
    然后,您可以通过管理界面或通过
    rest\u framework\u API\u key.models.APIKey
    对象以编程方式创建新的API键


    编辑:令牌也可以被撤销

    我在django rest framework jwt中没有发现任何撤销和重新激活行为。与Django rest
    authtoken
    相比的值在哪里?这取决于您到底想做什么。一种解决方案是从请求头中删除json web令牌。然后在需要的时候再添加一次。你能分享一下你最后做了什么吗?我也面临着同样的限制。只是把我的代码作为一个答案发布了。有一个带有到期时间的时间戳,偶尔自动更新令牌不是更好吗?或者在您的用例中不需要它?
    python manage.py migrate
    
    # settings.py
    REST_FRAMEWORK = {
        "DEFAULT_PERMISSION_CLASSES": [
            "rest_framework_api_key.permissions.HasAPIKey",
        ]
    }