web-dev-qa-db-ja.com

Django Rest Frameworkトークン認証

Django Rest Framework Guidesを読んで、すべてのチュートリアルを完了しました。すべてが理にかなっており、まさにその方法で動作するように見えました。説明どおりに基本認証とセッション認証を取得しました。 http://Django-rest-framework.org/api-guide

しかし、私はドキュメントのトークン認証の部分に苦労しています。それは少し欠けているか、チュートリアルほど深く掘り下げていません。
http://Django-rest-framework.org/api-guide/authentication/#tokenauthentication

ユーザー用のトークンを作成する必要があると書かれていますが、models.pyのどこに記載されていますか?

私の質問は:

誰かがドキュメントのトークン認証の部分を最初のタイマーについて少し良く説明できますか?

70
Prometheus

いいえ、models.pyにはありません-物事のモデル側では、適切なアプリを含めるだけです(rest_framework.authtokenINSTALLED_APPS。これにより、ユーザーに対して外部キーとなるトークンモデルが提供されます。

必要なのは、これらのトークンオブジェクトをいつどのように作成するかを決定することです。アプリでは、すべてのユーザーが自動的にトークンを取得しますか?または、特定の許可ユーザーのみですか?それとも、彼らが特に要求したときだけ?

すべてのユーザーが常にトークンを持っている必要がある場合は、リンクしたページにコードをスニペットして、自動的に作成する信号を設定する方法を示します。

@receiver(post_save, sender=User)
def create_auth_token(sender, instance=None, created=False, **kwargs):
    if created:
        Token.objects.create(user=instance)

(puts thisはmodels.pyファイルのどこにでもあり、Djangoスレッドの起動時に登録されます)

トークンを特定の時間にのみ作成する必要がある場合は、ビューコードで、適切な時間にトークンを作成して保存する必要があります。

# View Pseudocode
from rest_framework.authtoken.models import Token

def token_request(request):
    if user_requested_token() and token_request_is_warranted():
        new_token = Token.objects.create(user=request.user)

トークンが作成(および保存)されると、認証に使用できるようになります。

61
Ian Clelland

@ ian-clellandはすでに正しい答えを提供しています。彼の投稿で言及されていない小さな断片がいくつかありますので、完全な手順を文書化するつもりです(Django 1.8.5およびDRF 3.2.4)を使用しています:

  1. スーパーユーザーを作成する前に、 [〜#〜] [〜#〜] の前に次のことを行います。そうでない場合、スーパーユーザーは自分のトークンを作成しません。

  2. settings.pyに移動して、次を追加します。

    INSTALLED_APPS = (
        'rest_framework',
        'rest_framework.authtoken',
        'myapp',
    )
    
    REST_FRAMEWORK = {
        'DEFAULT_PERMISSION_CLASSES': (
            'rest_framework.permissions.IsAuthenticated',
        ),
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.TokenAuthentication',
        )
    }
    
  3. myappmodels.pyに次のコードを追加します。

    from Django.db.models.signals import post_save
    from Django.dispatch import receiver
    from rest_framework.authtoken.models import Token
    from Django.conf import settings
    
    # This code is triggered whenever a new user has been created and saved to the database
    @receiver(post_save, sender=settings.AUTH_USER_MODEL)
    def create_auth_token(sender, instance=None, created=False, **kwargs):
        if created:
            Token.objects.create(user=instance)
    

    または、より明確にしたい場合は、myapp projectの下にsignals.pyという名前のファイルを作成します。上記のコードをその中に入れてから、 __ init__.pyimport signalsと書きます

  4. コンソールウィンドウを開き、プロジェクトディレクトリに移動して、次のコマンドを入力します。

    python manage.py migrate
    python manage.py makemigrations
    

    データベースを調べて、 authtoken_token という名前のテーブルを次のフィールドで作成する必要があります。key(これはトークン値です)、created(作成された日時)、user_id( auth_userテーブルのid列を参照する外部キー)

  5. python manage.py createsuperuserでスーパーユーザーを作成します。ここで、select * from authtoken_token;を使用してDBの authtoken_token テーブルを見ると、新しいエントリが追加されていることがわかります。

  6. curlまたははるかに単純な代替 httpie を使用してAPIへのアクセスをテストするには、httpieを使用しています。

    http GET 127.0.0.1:8000/whatever 'Authorization: Token your_token_value'
    

    それでおしまい。今後、APIアクセスの場合は、HTTPヘッダーに次の値を含める必要があります( whitespaces に注意してください):

    Authorization: Token your_token_value
    
  7. (オプション)ユーザー名とパスワードを指定すると、DRFはユーザーのトークンを返す機能も提供します。あなたがしなければならないのは、 urls.pyに以下を含めることです:

    from rest_framework.authtoken import views
    
    urlpatterns = [
        ...
        url(r'^api-token-auth/', views.obtain_auth_token),
    ]
    

    Httpieを使用して確認:

    http POST 127.0.0.1:8000/api-token-auth/ username='admin' password='whatever'
    

    戻り本文には、これが表示されます。

    {
        "token": "blah_blah_blah"
    }
    

それでおしまい!

77
Cheng

On Django 1.8.2および上記のすべてに続くRESTフレームワーク3.3.2は、トークンベースの認証を有効にするのに十分ではありませんでした。

REST_FRAMEWORK設定はDjango設定ファイルで指定されていますが、関数ベースのビューには@api_viewデコレーターが必要です:

from rest_framework.decorators import api_view

@api_view(['POST','GET'])
def my_view(request):
    if request.user.is_authenticated():
       ...

それ以外の場合、トークン認証はまったく実行されません

14
Super S

これに2セントを追加するために、ユーザーの作成(およびアクティブ化)を処理するカスタムユーザーマネージャーがある場合は、次のようにこのタスクを実行することもできます。

from rest_framework.authtoken.models import Token
# Other imports

class UserManager(BaseUserManager):

    def create_user(self, **whatever_else):
        """
        This is your custom method for creating user instances. 
        IMHO, if you're going to do this, you might as well use a signal.

        """
        user = self.model(**whatever_params)
        .... #Method ramblings that somehow gave us a user instance
        Token.objects.create(user=user)

    #You may also choose to handle this upon user activation. 
    #Again, a signal works as well here.

    def activate_user(**activation_ramblings):
        .... #Method ramblings that somehow gave us a user instance
        Token.objects.create(user=user)

すでにユーザーが作成されている場合は、ターミナルのpython Shellにドロップダウンして、dbのすべてのユーザーのトークンを作成できます。

>>>from *whatever import User
>>>from rest_framework.authtoken.models import Token 
>>>for user in User.objects.all():
>>>...    Token.objects.create(user=user)

彼女が書いたのはそれだけです!それが誰かを助けることを願っています。

13
parsenz

ユーザートークンを取得するよりクリーンな方法があります。

manage.py Shellを実行するだけです

その後

from rest_framework.authtoken.models import Token
from Django.contrib.auth.models import User
u = User.objects.get(username='admin')
token = Token.objects.create(user=u)
print token.key

その後、テーブルDB_Schema.authtoken_tokenにレコードが見つかります

9

ここでの優れた回答に加えて、トークン認証へのより良いアプローチであるJSON Web Token Authenticationについて言及したいと思います。 http://getblimp.github.io/Django-rest-framework-jwt/ が提供する実装は非常に使いやすいです。

this answer で利点の詳細を説明しています。

5
Def_Os