Koki's personal blog

Koki's personal blog

Another fine, responsive site template by HTML5 UP.

Django REST frameworkでのCSRFトークン認証方法

Django REST frameworkを使用してWeb APIでCSRFトークン認証を行う方法を解説します。

Koki

3 分で読めます

この記事では、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.pyviews.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.pyviews.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)

最近の投稿

カテゴリー