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. The issue is that I want to generate an other token for this external api call that must be separate from auth system (f.i. like Mandrill API Keys or Github Personal Access Token). Is it a good solution to generate api keys from Django rest framework authtoken
Model ?
我已经在使用内置的Django rest auth令牌了,我打算发布一个其他的api,它将被外部集成调用,以便在我的Django应用程序中调用一些动作。问题是我想为这个外部api调用生成另一个令牌,该令牌必须与auth系统分开(f.i.如Mandrill API Keys或Github Personal Access Token)。从Django rest framework authtoken Model生成api密钥是一个很好的解决方案吗?
External api token:
外部api令牌:
- must never expire (it could expire in a session auth system)
- 必须永不过期(它可能会在会话auth系统中到期)
- 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 ;)
谢谢 ;)
2 个解决方案
#1
7
I have created a new authentication backend and a new token model to avoid side effect on build-in token behaviour.
我创建了一个新的身份验证后端和一个新的令牌模型,以避免对内置令牌行为产生副作用。
models.py
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
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}"
#2
2
If I understand you correctly, then Json Web Tokens is the solution for your needs. There is a really good django package available that integrates smoothly with django rest framework: django-rest-framework-jwt.
如果我理解正确,那么Json Web Tokens就是满足您需求的解决方案。有一个非常好的django包可以与django rest框架顺利集成:django-rest-framework-jwt。
With this package you can
有了这个包,你可以
- set the expiration time
- 设置到期时间
- reactivate or revoke the key
- 重新激活或撤消密钥
- determine from every external call to your api, if the token is valid
- 如果令牌有效,则从每次外部呼叫确定您的api
Still
仍然
Hope that helps.
希望有所帮助。
#1
7
I have created a new authentication backend and a new token model to avoid side effect on build-in token behaviour.
我创建了一个新的身份验证后端和一个新的令牌模型,以避免对内置令牌行为产生副作用。
models.py
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
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}"
#2
2
If I understand you correctly, then Json Web Tokens is the solution for your needs. There is a really good django package available that integrates smoothly with django rest framework: django-rest-framework-jwt.
如果我理解正确,那么Json Web Tokens就是满足您需求的解决方案。有一个非常好的django包可以与django rest框架顺利集成:django-rest-framework-jwt。
With this package you can
有了这个包,你可以
- set the expiration time
- 设置到期时间
- reactivate or revoke the key
- 重新激活或撤消密钥
- determine from every external call to your api, if the token is valid
- 如果令牌有效,则从每次外部呼叫确定您的api
Still
仍然
Hope that helps.
希望有所帮助。