Django csrf_token在chrome中为null

时间:2022-05-19 06:37:10

I'm having a bit of a strange problem. I am writing a simple little app and need to post some stuff back to a django view. I'm following the guide here: https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/ to set the ajax headers and have the following code in my js:

我有一个奇怪的问题。我正在写一个简单的小应用程序,需要将一些东西发回到django视图。我在这里遵循指南:https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/来设置ajax标头并在我的js中包含以下代码:

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

var csrftoken = getCookie('csrftoken');
console.log(csrftoken)

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});

I have a form in my html with the code:

我的html中有一个表单,代码如下:

<form onsubmit="return false;">
                {% csrf_token %}
                <input type="text" id="map-id-input"/>
                <button id="map-id-btn" class='btn btn-default custom-btn'>
                    Go 
                </button>
            </form>

I also have a snippet of js code that runs when the button above is clicked:

我还有一个js代码片段,当点击上面的按钮时会运行:

$(function() {
$("#map-id-btn").click(function() {
    checkMapID();
})
})

function checkMapID() {
    var mapId = $("#map-id-input").val();
    $.ajax({
        url: "check_map_id/", 
        type: "POST",
        dataType: "json", 
        data: {
            csrfmiddlewaretoken: csrftoken,
            map_id: mapId,
        },
        success: function(status_dict) {
            if (status_dict.status === 1) {
                $("#status").html("Valid map ID <br> Loading Data...")
                window.location = status_dict.url;
            }
            else {
                $("#status").html("Invalid map ID. Please try again, or contact ...")
            }
        },
        error: function(result) {
            console.log(result)
        }
    });
}

All of my Javacript is in one file, placed at the top of my template.

我的所有Javacript都在一个文件中,放在我模板的顶部。

The view that catches the url 'check_map_id/' is:

捕获url'check_map_id /'的视图是:

@ensure_csrf_cookie
def check_map_id(request):
map_id = request.POST['map_id']

if map_id not in GEOJSON_LOOKUP.keys():
    status = json.dumps({
        'status': 0,
        'url': '',
    })  
    return HttpResponse(status, content_type="application/json")
else:
    status = json.dumps({
        'status': 1,
        'url': reverse('map', args=(map_id,)),
    })
    return HttpResponse(status, content_type="application/json")

Now, when I run the app in my local machine using firefox, I get a valid csrf token being printed to the console. If I fire up the app on my local machine in chrome or IE I get a null being printed. The same behaviour is echoed on the live site. I'm using linux (mint) and strangely, if I fire up the app in firefox on a windows machine, it returns null in firefox too. Something strange is going on here! Any ideas? I seem to be doing exactly what the django documentation suggests.

现在,当我使用firefox在本地计算机上运行应用程序时,我得到一个有效的csrf令牌打印到控制台。如果我在我的本地机器上以chrome或IE启动应用程序,我会打印出一个null。在网站上回应相同的行为。我正在使用linux(薄荷),奇怪的是,如果我在Windows机器上启动firefox中的应用程序,它也会在firefox中返回null。奇怪的事发生在这里!有任何想法吗?我似乎正在完成django文档建议的内容。

UPDATE: I added @ensure_csrf_cookie to my index view and now I am getting a token printed out on both broswers on my local machine. The code is not working on my live server however. If I chuck some random console.logs in my js it displays on the live server so the code is being run. I'm really at a loss.

更新:我将@ensure_csrf_cookie添加到我的索引视图中,现在我在本地计算机上的两个broswers上都打印出一个令牌。但是,代码无法在我的实时服务器上运行。如果我在我的js中查看一些随机的console.logs,它会显示在实时服务器上,以便运行代码。我真的很茫然。

UPDATE2: So I have established that the problem is that on my live site, the document.cookie property is not being set. I guess the csrftoken="..." cookie is set by django. It seems to be setting it on my local machine but not on my live site. The code is identical :/. What on earth is going on here?!

更新2:所以我已经确定问题是在我的实时网站上,没有设置document.cookie属性。我想csrftoken =“...”cookie是由django设置的。它似乎是在我的本地机器上设置它而不是在我的实时站点上。代码完全相同:/。这到底是怎么回事?!

1 个解决方案

#1


4  

Ok. I have found the problem! It was a simple case of not actually sending the csrf token to the html page in the first place. I was focussing on the ajax call, which was actually correct.

好。我发现了问题!这是一个简单的例子,实际上并不是首先将csrf令牌发送到html页面。我专注于ajax调用,这实际上是正确的。

I changed the view that actually rendered the page the offending form was on to be:

我更改了实际呈现违规表单的页面的视图:

@ensure_csrf_cookie
def index(request):
    context = RequestContext(request)
    return render_to_response('vis_it_app/index.html', context)

The key here is 'RequestContext' which by default, send the csfr token as well. That was a mission...

这里的关键是'RequestContext',默认情况下也发送csfr令牌。那是一项使命......

So to summarise. To make this work.

总结一下。使这项工作。

  1. Ensure the csrf token is actually sent to the page you intend to use it on by using RequestContext and @ensure_csrf_cookie

    确保通过使用RequestContext和@ensure_csrf_cookie将csrf令牌实际发送到您打算使用它的页面

  2. Ensure {% csrf_token %} is somewhere in your form

    确保{%csrf_token%}位于表单中的某个位置

  3. Add the AJAX specific code found here: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax to your pages JavaScript

    在这里添加AJAX特定代码:https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax到您的页面JavaScript

  4. Make sure you send the middleware token back with the ajax data via:

    确保通过以下方式将中间件令牌与ajax数据一起发回:

    $.ajax({ url: "...", type: "POST", dataType: "...", data: { csrfmiddlewaretoken: csrftoken, ... },

    $ .ajax({url:“...”,类型:“POST”,dataType:“...”,数据:{csrfmiddlewaretoken:csrftoken,...},

And that should do it.

这应该做到这一点。

#1


4  

Ok. I have found the problem! It was a simple case of not actually sending the csrf token to the html page in the first place. I was focussing on the ajax call, which was actually correct.

好。我发现了问题!这是一个简单的例子,实际上并不是首先将csrf令牌发送到html页面。我专注于ajax调用,这实际上是正确的。

I changed the view that actually rendered the page the offending form was on to be:

我更改了实际呈现违规表单的页面的视图:

@ensure_csrf_cookie
def index(request):
    context = RequestContext(request)
    return render_to_response('vis_it_app/index.html', context)

The key here is 'RequestContext' which by default, send the csfr token as well. That was a mission...

这里的关键是'RequestContext',默认情况下也发送csfr令牌。那是一项使命......

So to summarise. To make this work.

总结一下。使这项工作。

  1. Ensure the csrf token is actually sent to the page you intend to use it on by using RequestContext and @ensure_csrf_cookie

    确保通过使用RequestContext和@ensure_csrf_cookie将csrf令牌实际发送到您打算使用它的页面

  2. Ensure {% csrf_token %} is somewhere in your form

    确保{%csrf_token%}位于表单中的某个位置

  3. Add the AJAX specific code found here: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax to your pages JavaScript

    在这里添加AJAX特定代码:https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax到您的页面JavaScript

  4. Make sure you send the middleware token back with the ajax data via:

    确保通过以下方式将中间件令牌与ajax数据一起发回:

    $.ajax({ url: "...", type: "POST", dataType: "...", data: { csrfmiddlewaretoken: csrftoken, ... },

    $ .ajax({url:“...”,类型:“POST”,dataType:“...”,数据:{csrfmiddlewaretoken:csrftoken,...},

And that should do it.

这应该做到这一点。