关于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);
posted @ 2020-03-24 00:53  帅气的日王  阅读(1902)  评论(0编辑  收藏  举报