【Django】Ajaxを利用したPOSTで403

2,042 views
Skip to first unread message

tonpa

unread,
Aug 31, 2012, 3:16:38 AM8/31/12
to djan...@googlegroups.com
こんにちわ

先日もお世話になったtonpaです。

django1.3で以下の用にPOSTをしたところ、403で返ってきてしまっているようです。

// post
$.post("/detail", {id: id} , function(data) { callback })

// view
def detail(request):
    if request.is_ajax():
        if request.method == 'POST':
            detail = Model.objects.get(id=csrf(request.POST['id']))
            return render_to_response('detail.html',
                                {'detail': detail},
                                context_instance=RequestContext(request))

また、以下に記載されているサンプルをコピーして読み込んでおります。

開発環境で開発中のときは期待通の動作をしておりましたが、
apacheにデプロイしてからは、403を返すようになってしまいました。

原因追及にご協力いただけませんでしょうか。

よろしくお願いいたします。


Toru Tomita

unread,
Aug 31, 2012, 4:53:13 AM8/31/12
to djan...@googlegroups.com
”403”はhttp status
codeであり、開発環境はdjangoのframeworkのwebserverで動いていたのであれば、デプロイ環境のApacheの設定におかしいところが在るのではないでしょうか?

http://ja.wikipedia.org/wiki/HTTP_403

どのような環境で動かされているのか不明なため、原因の推測が今案最低限、開発環境、動作環境(apacheデプロイ環境)などを記載頂かないと回答が難しいです。

※技術系メーリングリストで質問方法
http://www.hyuki.com/writing/techask.html


2012/8/31 tonpa <oniku.w...@gmail.com>:

> --
> ----------------- http://djangoproject.jp/ -----------------
> You received this message because you are subscribed to the Google Groups
> "django-ja" group.
> To post to this group, send email to djan...@googlegroups.com
> To unsubscribe from this group, send email to
> django-ja-...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/django-ja

tonpa

unread,
Aug 31, 2012, 10:48:28 AM8/31/12
to djan...@googlegroups.com
tonpaです。

早速の返信ありがとうございます。

環境について不足があり申し訳ありません。

// パッケージ
Apache/2.2.21
Django-1.3

// ディレクトリ構成
/Sites/my_site/
    |
    +----settings.py
    +----urls.py
    +---wsgi.py
    +---media
             |
             +---css
             +---img
             +---js
    +---my_app

// apache.conf
<VirtualHost *:80>
    DocumentRoot "/Sites/my_site/"
    ServerName my_app.com
    ErrorLog "/private/var/log/apache2/my_app-error_log"
    CustomLog "/private/var/log/apache2/my_app-access_log" common
    
    Alias /media/ /Sites/my_site/media/
    Alias /static/ /Sites/my_site/static/

    WSGIScriptAlias / /Sites/my_site/wsgi.py

    <Directory "/Sites/my_site/">
        AllowOverride None
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>


また、開発環境時はcontext_processorで以下のように設定しておりました。

// context_processor.py
import settings 

def media(request):
    return { 
        'MEDIA_URL': settings.MEDIA_URL,
    }

自分がおかしいと思う点が一点ありまして、
こちらのスクリプト上で、cookieにX-CSRFTokenをセットしているように見受けられるのですが、

  xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));

確認してみたところ実際のリクエストには、cookieにはX-CSRFTokenはnullとなっておりました。

原因の一因となるのかすら分かりませんが、よろしくお願いします。






2012年8月31日金曜日 17時53分13秒 UTC+9 Toru Tomita:

Toru Tomita

unread,
Aug 31, 2012, 11:57:26 PM8/31/12
to djan...@googlegroups.com
下記の設定は既に設定済みでしようか?
  1. Add the middleware'django.middleware.csrf.CsrfViewMiddleware' to your list of middleware classes, MIDDLEWARE_CLASSES. (It should come before CsrfResponseMiddleware if that is being used, and before any view middleware that assume that CSRF attacks have been dealt with.)

    Alternatively, you can use the decoratordjango.views.decorators.csrf.csrf_protect on particular views you want to protect (see below)

また
Postの際に、CSRFの値を含んでいるか気になります

Por iPhone

Toru Tomita

unread,
Aug 31, 2012, 11:58:53 PM8/31/12
to djan...@googlegroups.com

エラーログもあれば問題解決が早まるかもしれません

Por iPhone

On 2012/08/31, at 23:48, tonpa <oniku.w...@gmail.com> wrote:

tonpa

unread,
Sep 5, 2012, 11:39:01 AM9/5/12
to djan...@googlegroups.com
Toruさん

返信ありがとうございます。

CsrfViewMiddlewareに関しては、Django1.3にはデフォルトで有効になっているようです。


MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',               # こちら
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
)

CSRF値についてですが、
ajaxを利用する場合は、上記にも書きました
こちらの方で、cookieに値をセットする仕組みだと理解しておりました。
そこのリクエストで実際にnullとなってしまっているようで失敗していると考えております。

もし、他に確認する項目があるようでしたら、教えていただけたら幸いです。

よろしくお願いします。


2012年9月1日土曜日 12時57分43秒 UTC+9 Toru Tomita:

tonpa

unread,
Sep 5, 2012, 11:45:58 AM9/5/12
to djan...@googlegroups.com
自己レスですみません。

一応、view側をこちらを参考にして、

以下の用に施すことでajaxによるレスポンスを受け取れるようにはなりました。

// view.py
@csrf_exempt
def detail(request):
    if request.is_ajax():
        if request.method == 'POST':
            detail = Model.objects.get(id=request.POST['id'])
            return render_to_response('my_app/detail.html',
                                {'detail': detail},
                                context_instance=RequestContext(request))

ただ、この状態ですと、CSRF対策が出来てないことになると思うので、
あんまり好ましくないと思っているので、出来れば解決に至りたいです。



2012年9月6日木曜日 0時39分01秒 UTC+9 tonpa:

tsuyuki makoto

unread,
Sep 6, 2012, 3:16:24 AM9/6/12
to djan...@googlegroups.com
露木です。

状況を切り分けてみましょう。

ブラウザ上で動作しているJavaScriptで確認する事
===============================================
* Ajaxのリクエスト時に該当行が呼び出されているか

xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));

* Cookieにcsrftokenが設定されてきているか

Cookieにcsrftokenという名前と値がセットされてきているか。
csrftokenという名前は、settings.CSRF_COOKIE_NAMEで定義されています
ので、設定を変えていれば違う名前になるでしょう。

サーバ側でチェックする事
===============================================
* リクエストヘッダにX-CSRFTokenが設定されている事

CSRFViewMiddlewareのprocess_viewをみると、最終的には
request.META.get('HTTP_X_CSRFTOKEN', '') をチェックするようです。
リクエストヘッダを覗くか、METAを覗くかでHTTP_のプリフィックスが
あるかないかが違いそうなので、慌てずによく見るとよいでしょう。

原因となっている箇所がどこなのかを切り分けて、調査する必要の
ある場所を限りなく絞り込んでいくとよいと思います。

2012/9/6 tonpa <oniku.w...@gmail.com>:

in...@e-prism.jp

unread,
Aug 8, 2018, 5:21:51 AM8/8/18
to django-ja
こんにちは、私も同じ状況でしたが、ログイン状態だとうまく動きました。
createsuperuserでユーザを作成し、admin画面でログインしてから動かして見てください。

Reply all
Reply to author
Forward
0 new messages