目的
スロットリングの実装は以前に行い、APIを叩く回数に制限をかけることでブルートフォース攻撃などに対策を行なったが、それだけでAPIに関するセキュリティが万全と言えるわけもない。
**なぜなら誰でもAPIを叩ける状態になっているから。**そこでこのAPIを認証されたユーザーだけが制限された回数叩けるように認証周りを実装していきたい。
実施環境
ハードウェア環境
項目 | 情報 |
---|---|
OS | macOS Catalina(10.15.7) |
ハードウェア | MacBook Air (11-inch, Early 2015) |
プロセッサ | 1.6 GHz デュアルコアIntel Core i5 |
メモリ | 4 GB 1600 MHz DDR3 |
グラフィックス | intel HD Graphics 6000 1536 MB |
ソフトウェア環境
項目 | 情報 |
---|---|
homebrew | 3.3.8 |
mysql | Ver 8.0.27 for macos10.15 on x86_64 |
python | 3.8.12 |
anaconda | 4.10.1 |
django | 21.2.4 |
pip | 3.1.2 |
概要
usernameとpasswordでaccess_tokenを発行する時にはrefresh_tokenも同時に発行され、フロントのlocalStorageやCookieに保存される。
access_tokenの有効期限が切れている場合には、フロントのlocalStorageやCookieから有効期限がaccess_tokenよりも長いrefresh_tokenを利用してもう一度access_tokenを発行することができる
JWTトークンを取得する
###「Django REST framework JWT」インストール
$ pip install djangorestframework-simplejwt==4.6.*
setting.pyに設定を追加する
ACCESS_TOKEN_LIFETIMEはAuthトークンの有効期限を自分で好きな時間に変更する。
REST_FRAMEWORK = {
# jwtトークン認証
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
}
SIMPLE_JWT = {
'AUTH_HEADER_TYPES': ('JWT'),
# JWT有効期限
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=30),
}
設定ディレクトリのurls.pyにエンドポイントを実装する
simplejwtライブラリに入っているTokenObtainPairViewとTokenRefreshViewへのルーティングを実装
from django.contrib import admin
from django.db import router
from django.urls import path, include
from rest_framework_simplejwt import views
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/', include('tinder.urls')),
# jwt-tokenを取得
path('api-auth/jwt/', views.TokenObtainPairView.as_view()),
# jwt-tokenを再取得
path('api-auth/jwt/refresh', views.TokenRefreshView.as_view()),
]
postmanやcurlコマンドでAPIを叩く
画像のように、上記で実装したurls.pyのAPIエンドポイントを叩くと
※ トークンを取得するが、POSTメソッドでなければ許可されないため注意
※ usernameとpasswordをBodyに含める必要がある。
実際にJWT認証をViews.pyに適用する
下記のように指定のViewsの認証を追加する
from rest_framework.permissions import IsAuthenticated
class MemberViewSet(viewsets.ModelViewSet):
queryset = Members.objects.all()
serializer_class = MemberSerializer
# 今回の追加部分
permission_classes = (IsAuthenticated,)
viewごとにpermission_classesでどのような制限をかけるかを指定できる。
今回はMemberViewSetを利用できるのはログイン認証ができているユーザーのみ。
つまり、headerのAuthorizationに先ほど取得したaccess_tokenを入れてAPIエンドポイントを叩いた場合のみAPIを利用できる。
※ permission_classes = (IsAuthenticated,)
この部分で,
がないとエラーになるため要注意
access_tokenをHeaderに含めていない状態
認証状態が含まれていないと指摘される。
無事にこのAPIを叩くにはaccess_tokenが必要になったようだ
{
"detail": "認証情報が含まれていません。"
}
access_tokenをHeaderに含めた状態
headersのAuthorizationに先ほど取得したaccess_tokenを入れてもう一度APIを叩いてみる。
無事JSONデータを取得できた。