概要
リアクトネイティブ(React Native)で開発したアプリ(App)のログイン、情報更新などのAPIサーバーをジャンゴ(django)を使って開発してみようかと思っています。この時、アプリ(App)とAPIサーバーで良く使ってるJWT(Json Web Token)認証をジャンゴ(django)を使って実装してみようかと思っていました。このブログではDjango REST framework JWTを使ってジャンゴ(django)のJWTを実装する方法について説明します。
このブログで使ったソースコードはgithubに公開されております。下記のリンクで確認できます。
ジャンゴ(django)プロジェクトの準備
以前のブログシリーズでジャンゴ(django)のプロジェクトを使う方法について説明しました。ジャンゴ(django)を使ってプロジェクトを構成する方法について詳しく内容は下記のリンクを確認してください。
- ジャンゴ(django)インストール
- ジャンゴ(django)のプロジェクト開始
- ジャンゴ(django)のモデル(models)の使い方
- ジャンゴ(django)の管理者ページ
- ジャンゴ(django)のルーティング(Routing)
- ジャンゴ(django)のORM
- ジャンゴ(django)のビュー(View)
- ジャンゴ(django)のフォーム(Form)
- ジャンゴ(django)プロジェクトをヘロク(Heroku)へアップロードする
このブログではジャンゴ(django)のインストールやプロジェクトの設定などについては説明しません。簡単にプロジェクトが進めるレベルで説明します。
下記のコマンドでジャンゴ(django)のプロジェクトを生成します。
django-admin startproject django_response_model_to_json
下記のブログを参考してデーターベース連動やテーブルを作ります。
データーベースの連動が終わったら下記のコマンドで管理者(superuser
)を作ります。
python manage.py createsuperuser
下記のブログを参考してBlog
ジャンゴ(django)のアプリとPost
モデル(Model)を生成します。
そして下記のブログを参考してテストデーターを追加します。
Django REST framework JWTインストール
JWTの実装は結構面倒な部分が多いです。それで殆どのプラットフォームには良く作ったモジュールやライブラリが存在します。私たちはここでDjango REST framework JWTを使ってJWTを実装します。
下記のコマンドでDjango REST framework JWTをインストールします。
pip install djangorestframework djangorestframework-jwt
- djangorestframework: ジャンゴ(django)のRestful APIをもっと簡単に使えるようにしてくれるむジュールです。
- djangorestframework-jwt: ジャンゴ(django)のRestful APIでJWTを簡単に実装できるようにしてくれるモジュールです。
インストールが終わったら忘れなくrequirements.txt
を更新します。
pip freeze > requirements.txt
Django Rest framework JWT設定
Django Rest framework JWTを設定するためdjango_jwt/settings.py
を開いて下記のように修正します。
...
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}
JWT_AUTH = {
'JWT_SECRET_KEY': SECRET_KEY,
'JWT_ALGORITHM': 'HS256',
'JWT_ALLOW_REFRESH': True,
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=28),
}
...
もうちょっと詳しく見たら、
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
}
上部でインストールしたdjangorestframework
に関する設定です。
- ログインしたかどうかを確認するクラス(
DEFAULT_PERMISSION_CLASSES
)をrest_framework.permissions.IsAuthenticated
で使えるように設定します。 - ログインと関連するクラス(
DEFAULT_AUTHENTICATION_CLASSES
)をJWT(rest_framework_jwt.authentication.JSONWebTokenAuthentication
)を使えるように設定します。
JWT_AUTH = {
'JWT_SECRET_KEY': SECRET_KEY,
'JWT_ALGORITHM': 'HS256',
'JWT_ALLOW_REFRESH': True,
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=28),
}
- JWT_SECRET_KEY: JWTの秘密鍵(Secret Key)の設定です。ここではジャンゴ(django)と同じ秘密鍵を使えるようにしましたが本当は別の鍵を使えるように設定することをお勧めします。
- JWT_ALGORITHM: JWTの暗号化に使うアルゴリズムを指定します。
- JWT_ALLOW_REFRESH: JWTトークを更新(Refresh)できるようにするかを決めます。
- JWT_EXPIRATION_DELTA: JWTトークンの有効期限を設定します。
- JWT_REFRESH_EXPIRATION_DELTA: JWTトークンの更新の有効期限です。
JWT_EXPIRATION_DELTAとJWT_REFRESH_EXPIRATION_DELTAが良く理解できないですね。上のように設定するとJWTトークンは7日以内に更新(Refresh)しないとJWTトークンを使えなくなってログアウトされます。また7日以内に頑張って更新(Refresh)しても28日後には更新(Refresh)出来ないです。つまり、頑張って更新しても28日後にはログアウトされることを意味します。
Django Rest framework JWTのためURL設定
JWT認証のためURLを追加する必要があります。django_jwt/urls.py
を開いて下記のように修正します。
from django.contrib import admin
from django.urls import path, include
from rest_framework_jwt.views import obtain_jwt_token, verify_jwt_token, refresh_jwt_token
urlpatterns = [
path('admin/', admin.site.urls),
path('api/token/', obtain_jwt_token),
path('api/token/verify/', verify_jwt_token),
path('api/token/refresh/', refresh_jwt_token),
path('api/blog/', include('blog.urls'))
]
from rest_framework_jwt.views import obtain_jwt_token, verify_jwt_token, refresh_jwt_token
: JWT認証に必要な物を読んできます。- obtain_jwt_token: JWTトークンを発行する時使います。 (
path('api/token/', obtain_jwt_token)
) - verify_jwt_token: JWTトークンが有効かどうか確認する時使います。(
path('api/token/verify/', verify_jwt_token)
) - refresh_jwt_token: JWTトークンを更新(Refresh)する時使います。(
path('api/token/refresh/', refresh_jwt_token)
) - path(‘api/blog/’, include(‘blog.urls’)): 私たちが作ったBlogアプリのURLと連携します。
私たちが作ったBlogアプリのURLを作るためblog/urls.py
を開いて下記のように修正します。
from django.urls import path
from . import views
urlpatterns = [
path('posts/', views.posts, name='posts'),
]
ビュー(View)を作る
実際にJWT認証を使うAPIを作ってみましょう。blog/views.py
を開いて下記のように修正します。
from django.shortcuts import render
from django.core import serializers
from django.http import HttpResponse
from rest_framework.decorators import api_view, permission_classes, authentication_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from .models import Post
@api_view(['GET'])
@permission_classes((IsAuthenticated, ))
@authentication_classes((JSONWebTokenAuthentication,))
def posts(request):
posts = Post.objects.filter(
published_at__isnull=False).order_by('-published_at')
post_list = serializers.serialize('json', posts)
return HttpResponse(post_list, content_type="text/json-comment-filtered")
今まで作ってみたビュー(View)と形が違います。簡単にみてみます。
from django.shortcuts import render
from django.core import serializers
from django.http import HttpResponse
...
from .models import Post
...
def posts(request):
posts = Post.objects.filter(published_at__isnull=False).order_by('-published_at')
post_list = serializers.serialize('json', posts)
return HttpResponse(post_list, content_type="text/json-comment-filtered")
この部分は以前のブログ(ジャンゴ(django)のモデル(Models)をJSONタイプでレスポンス(Response)する)で説明しました。モデル(Models)の結果(QuerySet)をJSONでレスポンス(Response)するための部分です。じゃ、新しく追加された部分を見てみましょう。
...
from rest_framework.decorators import api_view, permission_classes, authentication_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
...
@api_view(['GET'])
@permission_classes((IsAuthenticated, ))
@authentication_classes((JSONWebTokenAuthentication,))
def posts(request):
...
from rest_framework.decorators import api_view, permission_classes, authentication_classes
: 私たちがインストールしたdjangorestframeworkが提供してるパイソンのデコレーター(Python Decorator)です。デコレーター(Decorator)を説明すると長くなるので、簡単に理解すると前処理と考えたら簡単と思います。from rest_framework.permissions import IsAuthenticated
: ログインしたかどうかをチェックする時使います。from rest_framework_jwt.authentication import JSONWebTokenAuthentication
: JWT認証を確認する時使います。@api_view(['GET'])
: 上で説明したデコレーター(Decorator)です。下にあるファンクション(def posts(request):
)を実行する前この部分が実行されます。このデコレーター(Decorator)はGET
リクエストかチェックしてGETじゃないとエラーをJSONタイプでレスポンスします。@permission_classes((IsAuthenticated, ))
: 権限をチェックします。ここではログインしたかどうかだけチェックします。@authentication_classes((JSONWebTokenAuthentication,))
: JWTトークンを確認します。トークンに問題があったらエラーをJSONタイプでレスポンスします。
確認
今まで作った内容をPostmanで確認してみます。下記のコマンドでジャンゴ(django)のテストサーバーを実行します。
python manage.py runserver
そしてPostmanを開いて下記のようにhttp://localhost:8000/api/blog/posts/
へGETリクエストを送ります。
そしたら上のようにエラーメッセージが確認できます。私たちが作ったAPIがJWT認証をちゃんと使ってることが確認できます。
それじゃ、JWT認証で情報を持てくるためJWTトークンを発行してみます。http://localhost:8000/api/token/
へPOSTでusername
とpassword
を設定してリクエストを送ります。ここで使ってusernameとpasswordは私たちが作ったジャンゴ(django)のsuperuser
です。(ジャンゴの管理画面にログインする時使ったusernameとpassword)
上のようにJWTトークンがうまく発行されたことが確認できます。発行されたJWTトークンを使ってもう一回上のリクエスト(http://localhost:8000/api/blog/posts/
)を送ってみます。ここではリクエストのHeader
にAuthorization
を設定して送ります。jwt [jwt key]
の形式で入れます。
以前と違ってデーターが取得できることが確認できます。次はJWTトークンを検証する方法と更新する方法について見てみます。JWTトークンを検証する方法はhttp://localhost:8000/api/token/verify/
へPOSTで上で発行して貰ったトークンを送信します。
そしたら、上のように問題がないことが確認できます。JWTトークンに問題があったら下記のようにエラーメッセージが帰ってきます。
じゃ、JWTトークンを更新(Refresh)してみましょうか?http://localhost:8000/api/token/refresh/
へPOSTで既に発行して貰ったJWTトークを送ります。
そしたら上のように新しJWTトークンが発行されます。もしJWTトークンを更新しなかった、有効期限で切れた場合、下記のようなエラーメッセージが帰ってきます。
完了
これでジャンゴ(django)でJWTを使う方法について見てみました。今からはJWTトークンを使ってアプリとサーバーの通信やフロントエンドとサーバー間通信へ使えます!
参考
- Django REST framework JWT: https://getblimp.github.io/django-rest-framework-jwt/
私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!
アプリ広報
Deku
が開発したアプリを使ってみてください。Deku
が開発したアプリはFlutterで開発されています。興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。