Django REST frameworkでのCSRFトークン認証方法
Django REST frameworkを使用してWeb APIでCSRFトークン認証を行う方法を解説します。
この記事では、Django REST frameworkを使用してWeb APIでCSRFトークン認証を行う方法を解説します。
この記事の内容です。
対象読者
- Django REST frameworkでREST APIを開発している方
- データ改ざんを防ぐための仕組みに興味がある方
- CSRFトークン認証の基本的な知識がある方
環境
以下は筆者の動作確認環境
- Python 3.11
- Django 4.2.2
- Django REST framework 3.14.0
前提条件
- DjangoとDjango REST frameworkがインストール済みであること
- Djangoプロジェクトが既にセットアップされていること
- REST APIの基本的な概念に馴染みがあること
CSRFトークン認証の導入方法
なぜCSRFトークン認証を導入するのか
REST APIの開発でも、フォーム送信データの改ざんを防ぐための仕組みを入れたい場合があります。
それを実現するために、CSRFトークン認証を導入し、POSTやPUT、PATCH、DELETEといったデータを変更するリクエストをサーバへ送る際にヘッダにCSRFトークンを含めることで検証を行い、フォーム送信データの改ざんを検知・ブロックすることが可能となります。
しかし、これはREST APIの作法に反しており、導入する際には注意が必要です。
(REST APIは状態を持つことを禁止している。)
CSRFトークンを返すAPIの実装
まず、CSRFトークンを発行し返すAPIを実装します。
以下のコードをWeb APIを実装するファイルに実装し、urls.pyへ登録し外部から実行できるようにします。
今回は、models.py
やviews.py
が存在するアプリディレクトリ配下にapis.py
というファイルを作成し、実装します。
from typing import Self
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView
class CSRFTokens(APIView):
def get(self: Self, request: Request) -> Response:
return Response({"token": get_token(request)})
認証クラスの作成
次に、CSRFトークン認証を行うためのコードを、models.py
やviews.py
が存在するアプリディレクトリ配下にauthentications.py
というファイルを作成し、実装します。
from rest_framework.authentication import SessionAuthentication
class CSRFOnlySessionAuthentication(SessionAuthentication):
def authenticate(self, request):
self.enforce_csrf(request)
return None
APIViewへの設定
次に、APIViewに上記で作成した認証クラスを設定します。以下はそのサンプルコードです。
from rest_framework.views import APIView
from .authentications import CSRFOnlySessionAuthentication
class SampleResources(APIView):
authentication_classes = [CSRFOnlySessionAuthentication]
# その他getやpostなどの処理
テスト時の注意点
テストコードでこの認証方法をテストする際は、APIClientを初期化する際にenforce_csrf_checks=Trueを渡さないと、CSRFトークン認証が無視されます。
CSRFトークンの有無や、検証のテストを行う場合は、必ず以下のようにAPIClient初期化時にパラメータでenforce_csrf_checks=True
を渡してください。
from rest_framework.test import APIClient
client = APIClient(enforce_csrf_checks=True)