Django mod_wsgiを使用してApacheサーバーで実行しているだけでなく、DjangoではなくApacheによって直接提供されているangularjsアプリもあります。POST Djangoサーバー(rest_frameworkを実行中)への呼び出しですが、csrfトークンに問題があります。
{% csrf token %}
をテンプレートの一部として配置せずにサーバーからトークンを設定する方法はありますか(これらのページはDjangoを経由しないため)?
DjangoとAngularJSの両方にCSRFのサポートが既にあり、あなたの部分は非常に簡単です。
まず、DjangoでCSRFを有効にする必要があります。すでに有効になっていると思います。そうでない場合は、Django doc https://docs.djangoproject.com/en/1.5/ref/に従ってください。 contrib/csrf /#ajax 。
これで、Djangoは最初のGETリクエストでcsrftoken
という名前のCookieを設定し、後のPOST/PUT/DELETEリクエストでカスタムHTTPヘッダーX-CSRFToken
を期待します。
Angularの場合、XSRF-TOKEN
という名前のCookieを想定し、X-XSRF-TOKEN
ヘッダーを使用してPOST/PUT/DELETEリクエストを実行するため、2つを相互に連携させるために少し調整する必要があります。
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
Jsコードのどこかに上記の2行を追加します。module.config()ブロックはこれに適しています。
それでおしまい。
注:これはangular 1.1.5用です。古いバージョンでは異なるアプローチが必要になる場合があります。
angularアプリはDjangoによって提供されないため、Cookieを設定するには、angularアプリはDjangoへのGETリクエストを最初に行う必要があります。
var foo = angular.module('foo', ['bar']);
foo.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);
そして、$ httpが使用されたすべてのモジュールサービスとコントローラーは、csrfトークンでリクエストを送信します。
周りを検索した後、私のために働いたのは this post からで、次のコードでした:
angular.module( '[your module name]',
... [some dependencies] ...
'ngCookies',
... [other dependencies] ...
)
.run( function run( $http, $cookies ){
// For CSRF token compatibility with Django
$http.defaults.headers.post['X-CSRFToken'] = $cookies.get('csrftoken');
})
もちろん、これはDjangoサーバーからGETリクエストを介してCookieを取得した後です。
Ye Liunを含む他のいくつかの回答も調べましたが、 this pull request 以外の、$ httpProviderのxsrfのデフォルトオプションの変更を指定する公式ドキュメントには何も見つかりませんでしたこの投稿を書いている時点では、私のために働くことはできません。
私は、AngularJSアプリ用のDjangoアプリを、同じ(= REST)API Djangoアプリと同じDjango 、index.htmlファイル(sym.linkのみ)のみを提供します。この方法では、追加のGETリクエストなしでCSRF Cookieが設定されます。
サブドメインAのAngularJSシングルページWebアプリケーションがCORSおよびCSRF保護を使用してサブドメインBのJSON(REST)APIと通信するDjango
JavaScriptアクセスを許可しないようにCookieを設定している場合、以下を実行する必要があります。テンプレートで、Djangoアプリを作成する前に、これを追加します。
<script>
window.csrf_token = "{{ csrf_token }}";
</script>
angularアプリで、これを追加します:
angularApp.config(["$httpProvider", function($httpProvider) {
$httpProvider.defaults.headers.common["X-CSRFToken"] = window.csrf_token;
}]);
少なくともDjango 1.9を介して、CSRFトークンはリクエストごとに変更されません。ユーザーがログインしたときにのみ変更されます。単一ページを行う場合angular = app、ログイン/ログアウト時にトークンをリセットすることを確認する必要があり、これは正常に動作するはずです。
注:現在、これはDjango 1.10以降ではCSRFトークンが各リクエストで変更されるため機能しません。 Pass Django Angular CSRF_COOKIE_HTTPONLYを使用