Django CSRF令牌在ajax请求中丢失。

3

编辑以备将来参考

解决:在 script.js 的 fetch 请求中,我使用了 Headers 而不是 headers,因此出现了 "Missing csrf token" 而不是 缺少或不正确的


所以我正在为一个“密码管理器”构建 Django 项目。我已经构建了我的模块,并通过 Django ModelForm 正确地实现了项目插入,包括 csrftoken 等。

现在我需要进行 ajax 请求以更新 Item 的字段,并希望在同一页上进行。因此,当打开 LoginItem 来编辑内容时,我会发送一个 GET 请求,如下所示:

//fetch django for a form, and it sends back pre filled with initial values

  fetch(`edit/login=id`)
    .then((response) => response.text())
    .then((form) => {

      const edit_form = document.createElement('form');
      edit_form.setAttribute("method", "post");
      edit_form.setAttribute("id", "edittest");
      edit_form.innerHTML = form;
     //append the form

然后在 script.js 文件中,在提交时:


    fetch(`edit/login=id}`, {
        method : "PUT",
        Headers:{
       //or "X-CSRFToken":event.target.querySelector('[name=csrfmiddlewaretoken]').value
            "X-CSRFToken": getCookie("csrftoken"),
            "Content-type": "application/json",
        },
        mode:"same-origin",
        body : JSON.stringify(body),
    })
    .then((response) => response.json())
    .then((data) => {
        console.log(data)
    })

在 Views.py 中

        def edit_login(request, id):
        if request.method == GET:
           login = Entry.objects.get(id=id)
            // setting initial values for the form
           initial = {
                "title": login.title,
                "username": login.username,
                "password": login.password,
                "note": login.note,
                "folder": login.folder,
                "protected":login.protected,
                "favorite": login.favorite,
            }
            // setting the initial values to the ModelForm
            form = LoginForm(initial=edit)

            return render(request, 'vault/new_item.html', {"entry_form": form, 'uri_field': uri})
      
         else if request.method == "PUT":
             if request.user == login.owner:

             data = json.loads(request.body)

             print("test") # execution does not reach here

            return JsonResponse({"message": "Succesfully edited"}, status = 200 ) # oppure 204 = No content
         

我收到了 Forbidden (CSRF token missing.): /edit/login=27 错误信息。

在 PUT 请求中,我尝试使用 "X-CSRFToken":event.target.querySelector('[name=csrfmiddlewaretoken]').value 来获取当前表单的 csrf 输入值,而不是使用 getCookie()。这给了我一个不同的 csrftoken,与之前的不同。

此外,如果我检查每个打开的元素,我会发现它们中的每一个都有一个不同的 csrftoken(好吧,不同的请求,因此我可以理解错误 Incorrect Token,但我不理解缺失错误)。

另外,如果有人知道更简单的方法,请提示一下,我对此了解有限。


这个回答解决了你的问题吗?Forbidden (CSRF token missing or incorrect.): - Sunderam Dubey
https://dev59.com/92cs5IYBdhLWcg3wlE82 - Sunderam Dubey
我似乎没有在那些我已经查看过的文章中找到解决方案, 困扰我的是,在检查表单后,我得到的csrf令牌与我在put请求之前console.log的令牌相同。 - Divroth
朋友指出了一个错误,原来是在获取请求中打错了字,使用了 Headers 而不是 headers - Divroth
1个回答

0
我解决这个问题最简单的方法是在数据中包含{{csrf_token}}值,而不使用Django中的@csrf_exempt装饰器(该装饰器将视图标记为免受中间件保护。):
var csrftoken = "{{csrf_token}}";

 //Sample ajax request
$.ajax({
    url: url,
    type: 'POST',
    headers:{
    "X-CSRFToken": csrftoken
},
data: data,
cache: true,
});

抱歉,我似乎不明白应该把第一行“var csrftoken = {{csrf_token}}”放在哪里。 这应该放在渲染表单的页面中的<script>标签内吗? 还是直接放在主要的script.js文件中?因为我之前在另一个项目中尝试过类似的操作,但无法使其正常工作。 - Divroth
1
你可以把它放在渲染表单的页面中的<script>标签里。 - Md.Imam Hossain Roni
我添加了那个,但表单现在消失了... 我还注意到另一个问题,我从Django得到的响应是<form action="/new_element" method="post"> 但我没有指定“post”方法或操作到new_element/ 我改变了Views.py指向一个新的edit_login.html,其中包含我从Django传递的表单,但我不明白“post”方法是从哪里获取的,或者为什么它具有该路径。 - Divroth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接