2

我正在使用 Daxice 库在我的 Django 应用程序中创建 AJAX 调用。当我在表单上创建POST方法时,出现上述错误:

Forbidden (403)
CSRF verification failed. Request aborted.

我的 settings.py 有:

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',
)

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.contrib.auth.context_processors.auth',
    'django.core.context_processors.debug',
    'django.core.context_processors.i18n',
    'django.core.context_processors.media',
    'django.core.context_processors.static',
    'django.core.context_processors.request',
    'django.contrib.messages.context_processors.messages',
    'django.core.context_processors.csrf',
)

我的网址.py

from django.conf.urls import patterns, include, url
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from dajaxice.core import dajaxice_autodiscover, dajaxice_config
dajaxice_autodiscover()

urlpatterns = patterns('',
    url(dajaxice_config.dajaxice_url, include('dajaxice.urls')),
    url(r'^$', 'apps.views.home'),
)

urlpatterns += staticfiles_urlpatterns()

我的意见.py:

from django.http import HttpResponse
from django.template import loader, Context

from django.core.context_processors import csrf

def home(request):
    t = loader.get_template('index.html')
    html = t.render(Context( ))
    return HttpResponse(html)

我的模板 index.html:

{% load dajaxice_templatetags %}

<html>
  <head>
    <title>My base template</title>

    <script src="http://code.jquery.com/jquery-latest.min.js"
        type="text/javascript"></script>

    {% dajaxice_js_import %}

    <script type="text/javascript">

    function shout(data){
        alert(data.message)

    }

    </script>
  </head>
  <body>

    <form method="POST" action="">{% csrf_token %}
        Page: <input type="text" name="page"><br>
        From: <input type="text" name="from"> (From < To) <br>
        To: <input type="text" name="to"> (returns results before that day)<br>
        <input type="submit" onclick="Dajaxice.apps.hello(shout);" value="Submit">
    </form>

    <br>
    <br>

    <input type="button" onclick="Dajaxice.apps.hello(shout);" value="Get message from server!">

   </body>
</html>

还有我的 ajax.py:

import simplejson
from dajaxice.decorators import dajaxice_register

@dajaxice_register(method='GET')
@dajaxice_register(method='POST', name='other_post')
def hello(request):
    return simplejson.dumps({'message':'Hello from Python!'})

如果我单击该按钮,则消息会收到警报。当我提交表单时,我收到此错误。我该如何解决?

最后,我相信我已经修复了调试页面中 CSRF 显示的所有可能性:

In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django's CSRF mechanism has not been used correctly. For POST forms, you need to ensure:
Your browser is accepting cookies.
The view function uses RequestContext for the template, instead of Context.
In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.
If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as well as those that accept the POST data.
4

3 回答 3

1

好吧,我想我明白了。在行中:

<form>
...
<input type="submit" onclick="Dajaxice.apps.hello(shout);" value="Submit"></form>
...
</form>

如果typebutton它的工作原理。它应该与submit服务器请求的行为有关。我不是解释为什么会发生这种情况的专家,所以如果有人可以解释,我很乐意投票。

于 2013-09-15T19:49:59.240 回答
1

根据文档,如果您首先运行此脚本,则可以在每个 ajax-post 请求上发送 csrf-token:

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function sameOrigin(url) {
    // test that a given url is a same-origin URL
    // url could be relative or scheme relative or absolute
    var host = document.location.host; // host + port
    var protocol = document.location.protocol;
    var sr_origin = '//' + host;
    var origin = protocol + sr_origin;
    // Allow absolute or scheme relative URLs to same origin
    return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
        (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
        // or any other URL that isn't scheme relative or absolute i.e relative.
        !(/^(\/\/|http:|https:).*/.test(url));
}
$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
            // Send the token to same-origin, relative URLs only.
            // Send the token only if the method warrants CSRF protection
            // Using the CSRFToken value acquired earlier
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});

它是用jquery编写的。如果你想要 vanilla js,请访问docs

于 2013-09-17T08:19:18.560 回答
1

Dajaxice 为您处理 CSRF,您不需要任何自定义 jQuery beforeSend 代码。

但是您需要授予 Dajaxice 访问您的 CSRF cookie 的权限。所以:

确保在您的 settings.py 中CSRF_COOKIE_HTTPONLY设置为False

于 2014-03-08T17:21:54.843 回答