サマリー
APIのエンドポイントを守れ!
準備するもの
- Pythonとpip
- Django RESTFrameworkのプロジェクト
Authってなに?
Authは認証のことで、Autheniticationの事を意味します。ここで、Authorizationと間違える事が多いですがこの2つは全くの別ものなのでちゃんと理解をしておきましょう。
Authentication(認証)→誰かを証明すること
Authorization(権限を与える)→特定のデータへのアクセスを許可するか
なのでAuth(認証)された人がどのPermissionがあるのかを判断する方法になり、それから、認証された人が特定のデータにアクセスできるかをAuthorizeするわけですね。
例でいうと会社のセキュリティカードを持っていればそのカードのステータスによってアクセスできる場所が決まってくるような感じでしょうか。
Authはなぜ必要か
APIのエンドポイントのURI(URL)にアクセスできる誰もがその情報を手に入れることができます。その情報を守るために認証された人だけにデータのアクセス権限を与えるためです。
特にデータの更新や削除ができる権限は限られた人だけに与えたいですよね。
Authの種類について
Djangoで主流なAuthシステムを紹介します。
- Basic Authentication→ログインIDとPWだけの簡単なものです。
- Token Authentication→トークンを使ってHTTP認証をします。クライアント・サーバーセットアップのデスクトップアプリやモバイルアプリに最適です。
- SessionAuthentication→DjangoについてくるセッションAuthのシステムを使えます。時間が経つとログアウトされる仕組みとかも作れます。
- 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を使うようにしましょう。