繁体   English   中英

“禁止(CSRF 令牌丢失或不正确。):”使用 Django 和 JS

[英]“Forbidden (CSRF token missing or incorrect.):” using Django and JS

我在我的 JS 代码中使用 Axios 执行 POST 请求,以将一些信息发送到我本地托管的 Django 服务器。 我的 html 代码表单中有 {% csrf_token %},但不知道如何使用 Axios 发送 csrf 令牌。

我在终端中收到此错误:“禁止(CSRF 令牌丢失或不正确。):/api/scoring/submit_score_details”。

如何在我的 axios 帖子中正确插入 csrf 令牌? 现在,我不认为 JS 可以像我一样读取 {{ csrf_token }}。 我一直在搜索 Stack,但似乎大多数人都在使用 jQuery 或其他一些类型的 JS。

为了节省空间,我没有发布有效负载中的变量是什么,但它们都只是字符串。

如果我将@csrf_exempt 放在views.py 文件中的function 上方,我可以得到go 的错误。

 { let payload = { "csrfmiddlewaretoken": "{{ csrf_token }}", "math_problem": problem, "user_answer": userInput, "true_answer": correctAnswer, "question_status": questionStatus, } console.log(payload); axios.post('../api/scoring/submit_score_details', payload) }
 <div class="col text-center"> <button id="start" type="button" class="btn btn-primary btn-lg"> New Problem </button> <p id="math_problem"></p> <form id="inputForm" method="POST"> {% csrf_token %} <input id="user_input" autocomplete="off" class="form-control form-control-lg" type="text" placeholder="Type your answer here"> <input id="correct_answer" type="hidden"> </form> <br> <button id="result_check" type="button" class="btn btn-primary btn-lg">Check</button> <script src={% static 'js/game_logic.js' %}></script> </div>

 { let payload = { "csrfmiddlewaretoken": "{{ csrf_token }}", "math_problem": problem, "user_answer": userInput, "true_answer": correctAnswer, "question_status": questionStatus, } console.log(payload); axios.post('../api/scoring/submit_score_details', payload) }
 <form id="inputForm" method="POST"> {% csrf_token %} <input id="user_input" autocomplete="off" class="form-control form-control-lg" type="text" placeholder="Type your answer here"> <input id="correct_answer" type="hidden"> </form>

所以我最终做了一些谷歌搜索并问了一个朋友。 我们想出了一个解决方案。

我们必须添加两行代码才能使事情正常进行:

axios.defaults.xsrfCookieName = 'csrftoken';
axios.defaults.xsrfHeaderName = 'X-CSRFToken';

我们还去掉了“有效负载”变量,将所有内容都放入 Axios 代码中。

 { axios.defaults.xsrfCookieName = 'csrftoken'; axios.defaults.xsrfHeaderName = 'X-CSRFToken'; axios.post('../api/scoring/submit_score_details', { "math_problem": problem, "user_answer": userInput, "true_answer": correctAnswer, "question_status": questionStatus, }); console.log(`Problem:${problem}, User Input: ${userInput}, Correct Answer: ${correctAnswer}, Question Status: ${questionStatus}` ); };
 <div class="col text-center"> <button id="new_problem_button" type="button" class="btn btn-primary btn-lg"> New Problem </button> <p id="math_problem"></p> <form id="inputForm" method="POST"> {% csrf_token %} <input id="user_input" autocomplete="off" class="form-control form-control-lg" type="text" placeholder="Type your answer here"> <input id="correct_answer" type="hidden"> </form> <br> <button id="result_check" type="button" class="btn btn-primary btn-lg">Check</button> <script src={% static 'js/game_logic.js' %}></script> </div>

这是一个帮助我们的链接。

是否可能在页面中呈现 csrf_token 之前创建您的 Axios 代码(通过 django 模板)?

在你的 js 代码中尽早尝试这样的事情:

var my_token = '{{ csrf_token }}';

然后当你调用 Axios 时,发送这个值,而不是渲染 {{ csrf_token }} 内联,所以是这样的:

{
    let payload = {
        "csrfmiddlewaretoken": my_token,
        "math_problem": problem,
        "user_answer": userInput,
        "true_answer": correctAnswer,
        "question_status": questionStatus,
    }
    console.log(payload);
    axios.post('../api/scoring/submit_score_details', payload)
}

我也很好奇您是否在显示的代码中看到您的 csrf 令牌被打印到控制台(从打印出有效负载),因为这将表明它是否正在发送。

如果正在发送 csrf_token,则应用程序可能会出现其他问题,但是一旦您在 my_token 中获得了令牌,您就可以将其打印出来并查看它是否已正确设置并从那里开始工作。

好吧,回头看看讨论,我想我可能知道这里发生了什么......

也许您在 JS 中添加了“{{ csrf_token }}”(存储在某处的 static 代码中)——这不起作用,因为正如您所指出的,JS 对 django 模板一无所知。

这样做的方法是更改您的 JS 代码以使用 JS 变量(例如 my_token)。

{
    let payload = {
        "csrfmiddlewaretoken": my_token, // populated later within form
        "math_problem": problem,
        "user_answer": userInput,
        "true_answer": correctAnswer,
        "question_status": questionStatus,
    }
    console.log(payload);
    axios.post('../api/scoring/submit_score_details', payload)
}

这个 my_token 值将在 Axios 调用之前提供(在您的表单中)。 为此,请在您的表单中添加:

<script>
    // This will be rendered by Django to get the actual string into my_token
    var my_token = "{{ csrf_token }}"; 
</script>

然后,当您调用 Axios 时(通过单击按钮或计时器或其他方式),应正确设置和使用此全局变量。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM