簡體   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