簡體   English   中英

如何使用包含憑據的提取和 POST 請求發送數據?

[英]How to send data using fetch and POST request with credentials included?

我想使用 fetch 從端口 3000 上的 React 前端向 3005 上的 node.js 服務器發送一些 JSON 數據。我在服務器上配置了 cors,但每次嘗試使用 cookie 發送請求時,Chrome 都會拋出錯誤:

CORS 策略已阻止從來源“ http: //localhost:3005/user-connected”訪問“ http://localhost:3005/user-connected ”:對預檢請求的響應未通過訪問控制檢查:值當請求的憑據模式為“include”時,響應中的“Access-Control-Allow-Origin”標頭不能是通配符“*”。

跳過來自服務器代碼的所有 console.log。

當我在獲取代碼中刪除標頭時

“內容類型”、“應用程序/json”

我收到 cookie,但沒有數據。 包含此標頭但沒有憑據:“include”,我可以獲得我的數據,但我永遠不會同時獲得兩者。

這是我的獲取代碼:

fetch("http://localhost:3005/user-connected", {
            mode: "cors",
            method: "post",
            headers: [
                ["Content-Type", "application/json"],
            ],
            credentials: "include",
            body: JSON.stringify({data: "123"})
        })
            .then(data => data.json())
            .then((data) => {
               console.log(`Response: ${JSON.stringify(data)}`);
            }).catch(err => {
                console.log(`Error: ${err}`)
        });

Node.js cors 配置:

app.use(cors({credentials: true}));

app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type', 'Access-Control-Allow-Origin', 'Origin');
  res.setHeader('Access-Control-Allow-Credentials', true);
  next();
});

還有我的發帖路線:

let cookiesData = (req, res) => {
  console.log(`Cookie user-connected: ${req.cookies.io}`)


  console.log(`Received data: ${JSON.stringify(req.body)}`);
  res.send({ status: "OK" });
}

router.post("/user-connected", cors({origin: 'http://localhost:3000'}), cookiesData);

甚至可以做我想做的事嗎? 或者我錯過了一些重要的配置?

您需要在 post 方法的獲取請求中傳遞這樣的標頭:

{
  credentials: 'include',
  mode: 'cors',
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
}

您必須確保已授予訪問權限 allow origin for localhost:3000

嘗試使用標頭作為對象:

headers: {
    "Content-Type": "application/json",
},

文檔Fetch Reference - Headers顯示帶有對象而非數組的示例

每當前端和后端之間的連接過程中發生錯誤時,通常最好將問題分離到這些端,所以首先讓我們完全忽略前端。 相反,我們可以使用 curl 或Postman查詢后端,通過它們您可以深入了解服務器實際返回的內容。

現在在您的情況下,CORS 飛行前請求是最重要的請求,並且可以通過向特定服務器路徑發送 OPTIONS 請求來檢查它是否正確設置。

然后您會發現, 不能同時使用通配符和憑據

現在,如果您更改路由本身的cors({... })選項,您會發現這不會影響返回的實際 OPTIONS 標頭。 也就是說,因為第一個cors()將終止所有 OPTION 請求並使用 uts 配置進行應答,所有進一步cors()中間件都不會改變任何東西。

因此,您應該添加一個全局 cors 處理程序:

  app.use(cors({origin: 'http://localhost:3000', credentials: true }));
 // don't use cors() again!

或者(這可能更好,因為它允許細粒度的訪問控制)將 cors 設置單獨添加到每個路由:

 app.use("/route", cors({origin: 'http://localhost:3000'}));
 app.get("/route", (req, res) => { /*...*/ });

您也可以將其添加到路由器,以便 cors 策略僅影響特定路徑。

添加 Content-Type 將在發送實際請求之前首先觸發預檢請求。 預檢請求方法是選項。 OPTIONS 不在請求標頭中包含 cookie(至少對於 Chrome 和 Firefox)。

錯誤可能是因為這段代碼:

console.log(`Cookie user-connected: ${req.cookies.io}`)

req.cookies 在預檢請求期間為 null,當您嘗試獲取 req.cookies.io 時會拋出錯誤。 預檢請求要求服務器返回 200(請參閱https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests )。 您的代碼有錯誤可能會拋出 500,從而向您顯示可怕的 CORS 錯誤消息。

您必須首先處理預檢請求。

在服務器端,嘗試處理 CORS 代碼中的 OPTIONS 方法以在 next() 之前返回 200:

app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type', 'Access-Control-Allow-Origin', 'Origin');
  res.setHeader('Access-Control-Allow-Credentials', true);

  if (req.method === 'OPTIONS') {
    res.sendStatus(200);
    return;
  }

  next();
});

這將阻止 next() 在預檢請求期間執行任何代碼,並告訴客戶端可以發送實際請求。

暫無
暫無

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

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