Django API Authってなに?Token Authenticationを使ってみよう

サマリー

APIのエンドポイントを守れ!
 

準備するもの

  • Pythonとpip
  • Django RESTFrameworkのプロジェクト

Authってなに?

Authは認証のことで、Autheniticationの事を意味します。ここで、Authorizationと間違える事が多いですがこの2つは全くの別ものなのでちゃんと理解をしておきましょう。

Authentication(認証)→誰かを証明すること

Authorization(権限を与える)→特定のデータへのアクセスを許可するか

なのでAuth(認証)された人がどのPermissionがあるのかを判断する方法になり、それから、認証された人が特定のデータにアクセスできるかをAuthorizeするわけですね。

例でいうと会社のセキュリティカードを持っていればそのカードのステータスによってアクセスできる場所が決まってくるような感じでしょうか。

Authはなぜ必要か

APIのエンドポイントのURI(URL)にアクセスできる誰もがその情報を手に入れることができます。その情報を守るために認証された人だけにデータのアクセス権限を与えるためです。

特にデータの更新や削除ができる権限は限られた人だけに与えたいですよね。

Authの種類について

Djangoで主流なAuthシステムを紹介します。

  1. Basic Authentication→ログインIDとPWだけの簡単なものです。
  2. Token Authentication→トークンを使ってHTTP認証をします。クライアント・サーバーセットアップのデスクトップアプリやモバイルアプリに最適です。
  3. SessionAuthentication→DjangoについてくるセッションAuthのシステムを使えます。時間が経つとログアウトされる仕組みとかも作れます。
  4. JWT(JSON Web Toekn)→ ここ数年で人気になったJSONウェブトークンでの認証システムです。

BasicAuthenticationを使おう

他にJWTとDjoserのライブラリもお勧めです。

まずは公式ドキュメンテーションを読みましょう。

https://www.django-rest-framework.org/api-guide/authentication/

settings.pyの設定

ではプロジェクトディレクトリ内のsettings.pyに下記のラインを追加しましょう。

REST_FRAMEWORK = {

    'DEFAULT_AUTHENTICATION_CLASSES': [

        'rest_framework.authentication.BasicAuthentication',

        'rest_framework.authentication.SessionAuthentication',

    ]

}

Views.pyの設定

ここでAiuthenticationに必要なモジュールをインポートします。

from rest_framework.authentication import SessionAuthentication, BasicAuthentication

from rest_framework.permissions import IsAuthenticated

あとは、クラスを貼り付けるだけ!

from .models import Member

from .serializers import MemberSerializer

from rest_framework import viewsets

#これを追加

from rest_framework.authentication import SessionAuthentication, BasicAuthentication

#これを追加

from rest_framework.permissions import IsAuthenticated




class MemberViewSet(viewsets.ReadOnlyModelViewSet):

    #これを追加

    authentication_classes = [SessionAuthentication, BasicAuthentication]

    #これを追加

    permission_classes = [IsAuthenticated]



    queryset = Member.objects.filter(status="Employed")

    # queryset = Member.objects.all()

    serializer_class = MemberSerializer

APIのエンドポイントの確認

では、DjangoのユーザーでログインしていないブラウザでURIにアクセスしましょう。

このように、APIのデータが出力されなくなりましたね。

ここで重要なのが、APIの発信元がHTTPSでないとログイン情報が盗まれることがあるので必ずHttps://を使うようにしましょう。

しかし、これだとDjangoのアドミンパネルからログインしていないとAPIが見れないのでクライアント側では使えなさそうですね。

(※このログインページはカスタマイズできますが次の方法で試してみましょう。)

TokenAuthを使おう

ではAuthのイメージが沸いたところでTokenAuthの設定をしていきます。

settings.pyの設定

では、REST_FRAMEWORKの項目を下記のように更新しましょう。

REST_FRAMEWORK = {

    'DEFAULT_AUTHENTICATION_CLASSES': [

        'rest_framework.authentication.TokenAuthentication'

    ],

    'DEFAULT_PERMISSION_CLASSES': [

        'rest_framework.permissions.IsAuthenticated'

    ]

}

では、Views.pyのAuthも項目は一旦削除しましょう。

で、APIのエンドポイントに行くとデータが見れなくなったことがわかりましたね。

http://127.0.0.1:8000/api/?format=api

このAPIのルートから全てTokenがないとアクセスが制限されます。

ちなみにこれをなくして、viewごとでauth設定をすることもでき、一部のapiだけにauthをかけられます。

Tokenを取得するURLを作成

まずはsettings.pyに下記のtokenアプリを追加します。

INSTALLED_APPS = [

    ...

    'rest_framework.authtoken'

]

ではurls.pyにTokenを作成するURLを作成します。

from rest_framework.authtoken import views




urlpatterns = [

    path('api-token-auth/', views.obtain_auth_token, name='api-token-auth')

]

URLの名前はなんでもよいです。

アプリを登録した後にDBのマイグレーションを忘れないようにしてください。

これでToeknテーブルがアドミンパネルに表示されました。

これでユーザーがログインしたときに生成されるトークンと照らし合わせてアクセス権限を判断できるようになります。

ログイン情報を作成

もし、ログインする情報がない人は先にスーパーユーザーを作っておきましょう。

python manage.py createsuperuser

テストでリクエストを送ってみる

では下記のURLにアクセスしてみます。

http://127.0.0.1:8000/api-token-auth/

下記のようにGETリクエストが拒否されました。

ではログイン情報と一緒にPOSTメソッドでリクエストを送ってみます。

HttpieでURLにPOSTリクエストを送る

では下記のコマンドでテストツールのhttpieをインストールします。

pip instal httpie

で、先ほど作成したapi-token-authのURLにPOSTリクエストを送ります。

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

これでTokenが作成されればOKです。

トークンを使ってAPIにアクセスする

では先ほど作成されたTokenを使ってAPIにアクセスできるか試してみましょう。

http http://127.0.0.1:8000/api/tickets/ “Authorization: Token 330b6d34c6ac24a3606b14495e9311e0681821c2”

問題なくレスポンスがかえってきましたね。

※同じようにHTTPSを使うようにしましょう。