2016-03-21 19 views
5

私は既にDjangoのビルド・イン・スタンダードを使用しています。私はDjangoアプリケーションで何らかのアクションを呼び出すために外部の統合によって呼び出される他のAPIをリリースする予定です。問題は、認証システム(Mandrill APIキーまたはGithubパーソナルアクセストークンのようなf.i.)とは別のこの外部API呼び出しのための他のトークンを生成したいということです。それはDjangoの残りのフレームワークauthtokenモデルからAPIキーを生成するための良いソリューションですか?ApiキーとDjango Restフレームワーク認証トークン

外部APIトークン:

  • を取り消すことができた(アカウントにリンクされている場合)
  • は、ユーザーにリンクではなく、要求される可能性(それはセッション認証システムに有効期限が切れる可能性が)有効期限が切れてはなりません再アクティブ化されました

apiキーを公開した経験はありますか?

Django Rest Frameworkが推奨するベストプラクティスですか?

はありがとう;)

+0

あなたがやって終わるんでした何を共有することはできますか?私は同じ制約に直面しています。 –

+0

私のコードを答えとして公開しました。http://stackoverflow.com/a/38913644/2551769 – jsan

答えて

7

ビルドイントークンの動作に悪影響を与えないように、新しい認証バックエンドと新しいトークンモデルを作成しました。

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 

あなたがセキュアなAPIを要求することができます次に

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) 

authentication.py:

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

期限切れのタイムスタンプを持ち、しばらくの間トークンを自動的に更新するほうがよいでしょうか?あなたのユースケースでは必要ないのですか? –

+0

私の場合、永久的なapi-keyが必要です。 – jsan

2

私が正しくあなたを理解していれば、その後、Json Web Tokensがニーズのためのソリューションです。 django rest framework:django-rest-framework-jwtとスムーズに統合できる、本当に良いdjangoパッケージがあります。あなたは

  1. が有効期限に
  2. アクティブ化を設定するか、トークンが有効であれば、キー
  3. は、あなたのAPIへのすべての外部呼び出しから決定取り消すことができます。このパッケージに

まだ

希望に役立ちます。

+0

django-rest-framework-jwtで取り消しと再活動化の動作が見つかりません。 Djangoの 'authtoken'と比較した値はどこですか? – jsan

+0

これは、あなたがしたいことによって異なります。 1つの解決策は、リクエストヘッダからjsonウェブトークンを除去することであろう。必要に応じて再度追加します。 – niklas

関連する問題