Webエンジニアの日常とリーグオブレジェンド

Webエンジニアとして働いている猫のブログ。EmacsとMySQLとリーグオブレジェンド(LoL)が好物。主に技術的な記事かLoLの記事を書く。

DjangoのクラスベースビューでSCRFトークンを無効化する

f:id:yoshiki_utakata:20181004212834j:plain

デバッグ時などにDjangoのクラスベースビューでCSRFトークンを一時的に無効化したいときの方法です。

例えばこういうAPIがあったとします。

from django.http import JsonResponse
from django.http import HttpRequest
from django.views import View

class ApiView(View):

    def post(self, request: HttpRequest, *args, **kwargs):
        data = {
            'status' => 'ok'
        }
        return JsonResponse(data)

これを普通にpostしようとすると死にます。例えば JS のライブラリである Axios を利用して

axios.post('/api')

とすると 403 エラーになります。

CSRFトークンを無効化する方法

デバッグなどのためにCSRFトークンを無効化します。

from django.http import JsonResponse
from django.http import HttpRequest
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator

class ApiView(View):

    def post(self, request: HttpRequest, *args, **kwargs):
        data = {
            'status' => 'ok'
        }
        return JsonResponse(data)

    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super(ApiView2, self).dispatch(*args, **kwargs)

このようにdispatchメソッドにcsrf_exemptをつけます。

根本解決

axiosのリクエスト時に X-CSRFToken ヘッダをつけるのが正しいです。Djangoの場合CookieCSRF Tokenが入っています。jsの js-cookie ライブラリを使うと便利です。

npm install js-cookie
import axios from 'axios'
import Cookies from 'js-cookie'

axios.post(`/api/sites/${this.siteId}/upload`, formData, {
  headers: {
    'X-CSRFToken': Cookies.get('csrftoken')
  }
});

参考

dackdive.hateblo.jp

Python Django 超入門

Python Django 超入門