【问题标题】:CSRF verification failed. Request aborted. // Dajaxice, AjaxCSRF 验证失败。请求中止。 // 达贾西斯,阿贾克斯
【发布时间】:2013-09-19 22:06:55
【问题描述】:

我正在使用 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',
)

我的 urls.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.

【问题讨论】:

  • 你用的是什么版本的 django?

标签: python django csrf django-csrf dajaxice


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    根据docs,如果您先运行此脚本,您可以在每个 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 编写的。如果你想要香草js,请访问docs

    【讨论】:

      【解决方案3】:

      好吧,我想我明白了。行内:

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

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

      【讨论】:

      • 如果您在第二种输入类型中谈论按钮,那是正常的,因为它不在表单中。
      • 我一直没能找到它,但我看到 {% csrf_token %} 模板标签生成的隐藏输入字段有点不稳定(并且使用了错误的 CSRF 令牌) .出于调试目的,您也可以通过以下方式将 CSRF 令牌添加到页面的 中: 然后,检查页面并查看隐藏的输入是否与头部中存在的 csrf 令牌匹配。
      猜你喜欢
      • 2013-10-28
      • 2010-10-11
      • 1970-01-01
      • 1970-01-01
      • 2018-05-15
      • 2018-07-04
      • 1970-01-01
      • 2014-07-01
      • 2023-03-21
      相关资源
      最近更新 更多