21
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

DjangoでAngularJSを使うときにCSRF Protectionを解決する方法

Posted at

概要

Djangoで標準のViewやDjango REST frameworkなどで作成したエンドポイントに対して、AngularJSのHttpProviderでpostすると、403エラーが返ってくる。

$http.post('/api/entries', {'title': '日記', 'body': '今日はいい天気です'})

Response

{detail: "CSRF Failed: CSRF token missing or incorrect."}

原因

これは、AngularJSを使っていることはあまり関係なく、DjangoのCSRF Protectionを上手く回避できていないのが原因。

CSRF Tokenを格納するRequest Headerの値が、AngularJSがデフォルトで使用する値と、Djangoが認識する値で違っているのに由来しているらしい。

以下のドキュメントを読むと、Djangoでは、Ajaxリクエストをするときに、csrftokenの値をX-CSRFTokenというヘッダ名で送信しないといけない。

Cross Site Request Forgery protection | Django documentation | Django

解決策

AngularJSのHTTPProviderには、CSRF Protectionの挙動を変更するオプションが用意されており、これを指定してあげると、CSRF Tokenを送る際のヘッダ名や、参照するcookieのキーを変更できる。

AngularJS: API: $http

Django向けの設定を行うには以下のように設定してあげると良い。

var myApp = angular.module('myApp', []).config(function($httpProvider) {
	$httpProvider.defaults.xsrfCookieName = 'csrftoken'
	$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'
});

これで、特に何もせずとも、AngularJSが自動的にcsrftokenを解釈して送信してくれる。めでたい。

余談

DjangoでAngularJSを使うにはもう一ヶ所ハマりどころがあって、AngularJSの変数展開がDjangoのテンプレートエンジンと競合しているため、デフォルトでは変数展開を行うことができない。

下記を参照にシンボルを変更すると幸せになれる。

AngularJS と jinja2 の変数スコープの競合を解決する方法 - Qiita

21
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?