CSRF令牌不适用于AJAX查询

时间:2016-01-18 13:15:34

标签: jquery ajax django

我已尝试按照this指南获取CSRF令牌以发送POST请求,但我总是收到403错误。

我的主页位于/,其中包含打开模态的链接。点击链接后,网址将更改为/#modal。当用户键入电子邮件/通行证并单击帖子链接时,它会返回403错误,并显示消息CSRF token missing or incorrect。我的基页包含脚本导入和模态,如下所示:

<!doctype html>
{% load staticfiles %}
<html class="no-js" lang="en">
<head>
  <meta charset="utf-8" />
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Freelance Student</title>
  <link rel="stylesheet" href="{% static 'css/normalize.css'%}">
  <link rel="stylesheet" href="{% static 'css/style.css'%}" />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
    <link rel="stylesheet" href="{% static 'css/jquery.remodal.css' %}">
</head>
<body>
  <header class="site-header">
    <div class="container">
      <div class="site-logo two">
        <img src="{% static 'img/logo.png' %}" alt="">
      </div>

      <nav role="navigation" class="nav-collapse">
        <ul class="site-nav">
        <li><a href="#">Talent Search</a></li>
        <li><a href="#">Employers</a></li>
        <li><a href="#">About</a></li>
        <li><a href="#modal">Login</a></li>
        <li><a href="#modal2" class="button green">Create a profile</a></li>
      </ul>
    </nav>
    <div class="remodal" data-remodal-id="modal">
      <div class="login">
        <div class="favicon"><img src="{% static 'img/favicon.png' %}" /></div>
        <div class="login-iner">
          <form id="login" method="post" action="#">
                {% csrf_token %}
                {{login_form.as_p}}
              <a id="post" href="">post</a>
            <!--<input type="submit" value="Login" />-->
          </form>
        </div>
        <p>Forgot username/password? <span class="lspan"><a href="#">Click here</a></span></p>
      </div>
    </div>
    <div class="remodal" data-remodal-id="modal2">
      <div class="logot">
        <div class="favicon"><img src="images/favicon.png" /></div>
        <h1>Complete the form to build your profile</h1>
        <div class="logot-iner">
          <form>
          <p>
            My name is &nbsp;&nbsp;
            <input type="text" placeholder="first name" />
            &nbsp;&nbsp;
            <input type="text" placeholder="last name" />
            and I am a  &nbsp;&nbsp;<span class="type">
            <input type="text" placeholder="student type" />
            </span> &nbsp;&nbsp; Student
            <br />
            <br />
            I am completing a  &nbsp;&nbsp; <span class="type">
            <input type="text" placeholder="degree type" />
            </span> &nbsp;&nbsp; degree at<br />
            <span class="type1">
            <input type="text" placeholder="uni/college" />
            </span>
            <br />
            <br />
            I study/studied &nbsp;&nbsp; <span class="type2">
            <input type="text" placeholder="degree subject" />
            </span> &nbsp;&nbsp;and I
            am currently in my &nbsp;&nbsp;<span class="type">
            <input type="text" placeholder="select year" />
            </span> &nbsp;&nbsp; year.
            <br />
            <br />
            DOB: &nbsp;&nbsp; <span class="type3"><input type="text" placeholder="DD" /></span>&nbsp;&nbsp;
             <span class="type3"><input type="text" placeholder="MM" /></span> &nbsp;&nbsp;
              <span class="type3"><input type="text" placeholder="YYYY" /></span> &nbsp;&nbsp;
            <br />
            <br />
            My primary skill area is &nbsp;&nbsp; <span class="type">
            <input type="text" placeholder="skill area" />
            </span> &nbsp;&nbsp;<br />
            <br />
            <span class="lspan1">You must be at least 18 years of age to join</span><br />
            <br />
            <input type="submit" value="Sign up" />
          </p>
          </form>
        </div>
      </div>
    </div>
  </div>
  <!-- /.container -->
</header>
<!-- /.site-header -->
  {% block content %} {% endblock %}

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
  <script src="{% static 'js/vendor/responsive-nav.min.js' %}"></script>
  <script src="{% static 'js/main.js' %}"></script>
  <script src="{% static 'js/base.js' %}"></script>
  <script src="{% static 'js/vendor/jquery.min.js' %}"></script>
  <script src="{% static 'js/jquery.remodal.js' %}"></script>

</body>
</html>

相关的JavaScript文件如下:

$(document).ready(function(){

    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;
    }

    $.ajaxSetup({
        beforeSend: function(xhr, settings) {
            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'));
            }
        }
    });


    $('a#post').on('click', function(e) {

        e.preventDefault();

        $.ajax({
            type : 'POST',
            url  : window.location.href,
            dataType: 'json',
            data: {'foo': 'bar'},
            beforeSend: function(xhr, settings) {
                console.log("Before Send");
                $.ajaxSettings.beforeSend(xhr, settings);
            },
            success: function(data){
                console.log(data);
            },
        });
    });
});

我不明白我错过了什么?我已加入{% csrf_token %},JavaScript正在向控制台打印Before Send

1 个答案:

答案 0 :(得分:1)

您已将您的beforeSend功能编写为仅将CSRF发送到本地网址,即那些不以httphttps开头的网址。但是,您只需获取 包含该字符串的window.location.href,就可以生成Ajax发送到的URL。您需要使用相对URL,或更改beforeSend中的逻辑。

另请注意,您不应该直接调用该方法;调用ajaxSetup的全部意义在于它会自动执行此操作。移除实际beforeSend电话的.ajax部分。