[解決済み】AjaxのPOSTリクエストでDjangoのCSRFチェックが失敗する件
質問
私の AJAX 投稿で、Django の CSRF 保護メカニズムに準拠するための手助けが欲しいです。私はここの指示に従いました。
http://docs.djangoproject.com/en/dev/ref/contrib/csrf/
そのページにあるAJAXのサンプルコードを正確にコピーしました。
http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
の内容を表示するアラートを設置しました。
getCookie('csrftoken')
の前に
xhr.setRequestHeader
を呼び出すと、確かに何らかのデータが入力されています。トークンが正しいかどうかを確認する方法はわかりませんが、何かを見つけて送信してくれているようで心強いです。
しかし、Djangoはまだ私のAJAXポストを拒否しています。
これが私のJavaScriptです。
$.post("/memorize/", data, function (result) {
if (result != "failure") {
get_random_card();
}
else {
alert("Failed to save card data.");
}
});
以下は、Djangoから表示されるエラーです。
[23/Feb/2011 22:08:29] "POST /memorize/ HTTP/1.1" 403 2332
何か見落としていると思うし、単純なことかもしれないが、それが何なのか分からない。 SOを検索してみたところ、ビューのCSRFチェックをオフにするには
csrf_exempt
デコレーターがありますが、それは魅力的ではありませんね。 しかし、できれば Django が期待するように設計された方法で POST を動作させたいと思っています。
一応、私のビューがやっていることの要点は以下のとおりです。
def myview(request):
profile = request.user.profile
if request.method == 'POST':
"""
Process the post...
"""
return HttpResponseRedirect('/memorize/')
else: # request.method == 'GET'
ajax = request.GET.has_key('ajax')
"""
Some irrelevent code...
"""
if ajax:
response = HttpResponse()
profile.get_stack_json(response)
return response
else:
"""
Get data to send along with the content of the page.
"""
return render_to_response('memorize/memorize.html',
""" My data """
context_instance=RequestContext(request))
ご返信ありがとうございます。
どのように解決するのですか?
実際の解決策
OK、問題を突き止めることに成功しました。それは、Javascriptのコードにあります(以下に提案します)。
必要なのは、これです。
$.ajaxSetup({
beforeSend: function(xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
の代わりに、公式ドキュメントに掲載されているコードを使用します。 https://docs.djangoproject.com/en/2.2/ref/csrf/
動作するコードは、このDjangoのエントリにあります。 http://www.djangoproject.com/weblog/2011/feb/08/security/
つまり、一般的な解決策は、「ajaxSendハンドラの代わりにajaxSetupハンドラを使用すること」"です。なぜそれがうまくいくのか、私にはわかりません。しかし、私にとってはうまくいっています :)
前の記事(回答なし)
実は私も同じ問題を経験しています。
Django 1.2.5 にアップデートした後に発生します。Django 1.2.4 では AJAX POST リクエストでエラーは発生しませんでした (AJAX は何ら保護されていませんでしたが、問題なく動作していました)。
OPと同じように、Djangoのドキュメントに掲載されているJavaScriptのスニペットを試してみました。私は jQuery 1.5 を使っています。また、私は "django.middleware.csrf.CsrfViewMiddleware" ミドルウェアを使用しています。
私はミドルウェアのコードに従おうとし、私はそれがこの上に失敗することを知っています。
request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')
そして
if request_csrf_token != csrf_token:
return self._reject(request, REASON_BAD_TOKEN)
request_csrf_token" が空なので、この "if" は真です。
基本的には、ヘッダーが設定されていないことを意味します。ということは、このJSの行に何か問題があるのでしょうか。
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
?
提供された詳細が問題解決の一助となることを願っています :)
関連
-
Pythonコンテナのための組み込み汎用関数操作
-
[解決済み】「RuntimeError: dictionary changed size during iteration」エラーを回避する方法とは?
-
[解決済み] データ型が理解できない
-
[解決済み】socket.error: [Errno 48] アドレスはすでに使用中です。
-
[解決済み] TypeError: 'DataFrame' オブジェクトは呼び出し可能ではない
-
[解決済み】ValueError: xとyは同じサイズでなければならない
-
[解決済み] jQuery Ajax呼び出し後のリダイレクトリクエストを管理する方法
-
[解決済み] どうすればjQueryに非同期ではなく、同期のAjaxリクエストを実行させることができますか?
-
[解決済み] CORSです。資格情報フラグが true の場合、Access-Control-Allow-Origin でワイルドカードを使用できない。
-
[解決済み】PHPによるjQuery Ajax POSTの例
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Pythonコンテナのための組み込み汎用関数操作
-
Python 入出力と高次代入の基礎知識
-
[解決済み】RuntimeWarning: invalid value encountered in double_scalars で numpy の除算ができない。
-
[解決済み] データ型が理解できない
-
[解決済み】numpy: true_divide で無効な値に遭遇
-
[解決済み】TypeError: re.findall()でバイトのようなオブジェクトに文字列パターンを使用することはできません。)
-
[解決済み】SyntaxError: デフォルト以外の引数がデフォルトの引数に続く
-
[解決済み】Flask ImportError: Flask という名前のモジュールがない
-
[解決済み】NameError: 名前 'self' が定義されていません。
-
[解決済み】Python - "ValueError: not enough values to unpack (expected 2, got 1)" の修正方法 [閉店].