關於CORS(跨域資源共享)的幾個http請求頭小實驗


對幾種與跨域相關的請求頭做一個總結

關於跨域可以看:9 種常見的前端跨域解決方案(詳解)

看完后可以配合我的代碼做些實驗,看看注釋掉某個響應頭會發生什么,整體代碼會在最后貼出


1. 跨域簡單請求

需要在服務器響應頭中加 Access-Control-Allow-Origin

2. 跨域復雜請求

這時候會發送預檢請求options,服務器需要在響應頭中添加Access-Control-Allow-Headers來表明支持的請求頭

需要響應頭

  • Access-Control-Allow-Headers
  • Access-Control-Allow-Origin

響應頭中 Access-Control-Allow-Headers 的值應該設置為是使簡單請求變成非簡單請求的請求頭,有多個時則以逗號相連(當然,也可以設置為*)。在這里,因為發請求的時候我設置了

headers: {
          "content-type": "application/json" //設置這個后,就不是簡單跨域請求了
        },

所以 Access-Control-Allow-Headers 響應頭中至少要有 content-type

不加Access-Control-Allow-Headers則瀏覽器提示
Access to XMLHttpRequest at 'http://localhost:3333/test3' from origin 'http://localhost:2222' has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.

3. 跨域復雜請求,帶 cookie

需要響應頭

  • Access-Control-Allow-Headers,並且不能為 *
  • Access-Control-Allow-Origin,並且不能為 *
  • Access-Control-Allow-Credentials 為 true

4. 代碼

分了三個文件

4.1. test.html

在這里發送 ajax 請求

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>

  <body>
    <button type="button" id="test1">不跨域請求</button>
    <button type="button" id="test2">跨域簡單請求</button>

    <button type="button" id="test3">跨域復雜請求</button>
    <button type="button" id="test4">跨域復雜請求,帶cookie</button>
    <!-- <button type="button" id="test">測試</button> -->
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <script>
      var test1 = document.querySelector("#test1");
      //不跨域請求
      test1.addEventListener(
        "click",
        function() {
          var url = `/test1`;
          $.ajax({
            url: url,
            type: "get",
            data: {
              test: "test1"
            },
            success(res) {
              var modal = `<div>不跨域請求成功:${res}</div>`;
              $("body").append(modal); //htmlEscape()對字符進行轉義,js不會被執行,而是作為字符串
            }
          });
        },
        false
      );

      //跨域簡單請求
      var test2 = document.querySelector("#test2");
      test2.addEventListener(
        "click",
        function() {
          var url = `http://localhost:3333/test2`;
          $.ajax({
            url: url,
            type: "post",
            data: {
              test: "test2"
            },
            success(res) {
              var modal = `<div>跨域簡單請求成功:${res}</div>`;
              $("body").append(modal); //htmlEscape()對字符進行轉義,js不會被執行,而是作為字符串
            }
          });
        },
        false
      );

      // 跨域復雜請求
      var test3 = document.querySelector("#test3");
      test3.addEventListener(
        "click",
        function() {
          var url = `http://localhost:3333/test3`;
          $.ajax({
            url: url,
            type: "post",
            headers: {
              "content-type": "application/json" //設置這個后,就不是簡單跨域請求了
            },
            data: {
              test: "test3"
            },
            success(res) {
              var modal = `<div>跨域復雜請求成功:${res}</div>`;
              $("body").append(modal); //htmlEscape()對字符進行轉義,js不會被執行,而是作為字符串
            }
          });
        },
        false
      );

      // 帶cookie的跨域請求
      var test4 = document.querySelector("#test4");
      test4.addEventListener(
        "click",
        function() {
          var url = `http://localhost:3333/test4`;
          $.ajax({
            url: url,
            type: "post",
            headers: {
              "content-type": "application/json" //設置這個后,就不是簡單跨域請求了
            },
            xhrFields: {
              withCredentials: true // 前端設置是否帶cookie
            },
            data: {
              test: "test4"
            },
            success(res) {
              var modal = `<div>帶cookie的跨域請求成功:${res}</div>`;
              $("body").append(modal); //htmlEscape()對字符進行轉義,js不會被執行,而是作為字符串
            }
          });
        },
        false
      );
    </script>
  </body>
</html>

4.2. server.js

負責返回 test.html 和提供不跨域請求的接口

const fs = require("fs");
const http = require("http");
const qs = require("querystring");
const path = require("path");

http
  .createServer((req, res) => {
    let html = fs.readFileSync(path.resolve(__dirname, "./test.html"));
    const url = req.url.split("?")[0];
    const query = req.url.split("?")[1];
    req.on("data", function(data1) {
      postData += data1;
    });
    console.log("收到來自  ", url);
    if (req.method == "GET") {
      if (url == "/") {
        //返回html模板
        res.setHeader("set-cookie", "testCORS=riwang"); //設置cookie,后面發送帶cookie的請求時使用
        res.end(html);
      } else if (url == "/test1") {
        //不跨域請求
        res.end(query);
      }
    }
  })
  .listen(2222);

4.3. api.js

負責提供跨域請求的接口

/*
 * @Author: riwang
 * @Date: 2020-03-23 23:30:59
 * @LastEditTime: 2020-03-24 00:49:29
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \RW 筆記\web安全\跨域\code\api.js
 */

const fs = require("fs");
const http = require("http");
const qs = require("querystring");
const path = require("path");

http
  .createServer((req, res) => {
    let html = fs.readFileSync(path.resolve(__dirname, "./test.html"));

    const url = req.url.split("?")[0];
    const query = req.url.split("?")[1];
    const cookies = req.headers.cookie;
    var postData = "";
    req.on("data", function(data1) {
      postData += data1;
    });
    console.log("收到來自  ", url);
    if (req.method == "GET") {
      res.end(html);
    } else {
      res.setHeader("set-cookie", "testCORS");
      //跨域簡單請求
      if (url == "/test2") {
        res.setHeader("Access-Control-Allow-Origin", "*");

        req.on("end", function() {
          res.end(postData);
        });
      }

      if (url == "/test3") {
        res.setHeader("Access-Control-Allow-Origin", "*");
        res.setHeader("Access-Control-Allow-Headers", "*");
        req.on("end", function() {
          res.end(postData);
        });
      }

      if (url == "/test4") {
        res.setHeader("Access-Control-Allow-Origin", req.headers.origin);
        res.setHeader("Access-Control-Allow-Headers", "content-type"); //這里設置為*瀏覽器會報錯
        res.setHeader("Access-Control-Allow-Credentials", true);
        req.on("end", function() {
          res.end(`postBody是${postData} |||||| cookies是${cookies}`);
        });
      }
    }
  })
  .listen(3333);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM