簡體   English   中英

如何使用 fetch api 在 post 請求中正確驗證?

[英]How to authenticate properly in post request with fetch api?

  • 我有一個 SpringBoot 后端,在默認配置中啟用了 Spring Security(那里沒有任何變化)。

  • 我有以下 Rest Controller 和 Post Mapping:


@RestController
public class MyController {

    @PostMapping(value = "/sm/resrc/pth")
    public Integer postSomething(@RequestParam String someValue,@RequestParam String userId){
        System.out.println(String.format("SomeValue: %s from userid %s",someValue,userId));
        return 0;
    }

}
  • 從以下表單創建 Post 請求工作正常:
<form method="post" th:action="@{/sm/resrc/pth}">
     <input type="text" name="someValue">
     <input type="text" name="userId">
     <input type="hidden" name="_csrf" value="${_csrf.token}" />
     <div><input type="submit" value="Send" /></div>
</form>

它甚至可以在沒有隱藏 cors 值的情況下工作。

  • 但是我需要從 JavaScript 創建一個 post 請求,這不起作用。 SpringBoot 應用程序在localhost:8080 上運行。 我認為,憑證參數“include”用於包含所需的身份驗證標頭,用戶已成功輸入該標頭以打開給定頁面。 這樣對嗎? 我還更改了'mode'的值。 我試過'cors''same-origin''no-cors' 它只是不起作用。 我事件不明白為什么 cors 是一個問題,因為我正在請求來自同一來源的資源。 在不使用憑據參數的情況下將授權標頭手動添加到請求后,它甚至不起作用。正如您在圖像中看到的,我總是得到 403 狀態。 我的請求有什么問題? 我錯過了什么?
let data = {
            "some":"abc",
            "values":this.localDescription,
            "userId":userId
        };

fetch("sm/resrc/pth",
            {
                method: 'POST',
                credentials: 'include',
                mode: 'cors',
                body: data
            }
        ).then(response => console.log(response));

回復截圖

我在用 jax-rs 做一個登錄示例時發現了同樣的問題。 在我的情況下,問題是當向請求添加 'credentials': 'include' 時,在 Rest Service API 一側,需要在 CORS 過濾器中配置標頭:

response.addHeader("Access-Control-Allow-Origin", "*");

到:

res.addHeader("Access-Control-Allow-Origin", "http://localhost");

其中“http://localhost 是我請求的來源。

我在這篇文章中找到了有關它的信息: 請求的資源上不存在“Access-Control-Allow-Origin”標頭—當嘗試從 REST API 獲取數據時

CORS 是一項安全功能; 所以你可能不想禁用或繞過它。 我努力找出如何正確包含標題,但最終找到了解決方案。 我就是這樣解決的:

在第一步中,我將預期的 CSRF-Header-name 和令牌本身添加到生成的 html 文件的元數據中。 在春季使用模板框架 thyemleaf 時,它看起來如下所示:

<html lang="en">
    <head>
        <meta name="_csrf_header_name" th:content="${_csrf.headerName}"/> 
        <meta name="_csrf_token" th:content="${_csrf.token}"/>
               
    </head>
    .
    .
    .
</html>

結果是這樣的:


<meta name="_csrf_header_name" content="X-CSRF-TOKEN">
<meta name="_csrf_token" content="14d98c88-8643-1234-5678-39473aa7890e">

在獲取請求中,CSRF Header 是從令牌和正確的 Header-name(從元標記中讀取)構建的,正如服務器所預期的那樣。

getCsrfToken(){
   return document.querySelector('meta[name=_csrf_token]').content;
}

getCsrfTokenName(){
   return document.querySelector('meta[name=_csrf_header_name]').content;
}
 
let csrfToken = this.getCsrfToken();
let csrfTokenName = this.getCsrfTokenName();
        
fetch('sm/resrc/pth', {
          method:'post',
          headers: new Headers([[csrfTokenName, csrfToken]])
        }).then(res =>{console.log(res);});}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM