zoukankan      html  css  js  c++  java
  • 关于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安全跨域codeapi.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);
    
  • 相关阅读:
    转: sql语句获取本周、本月数据
    Java 程序中的静态代码块
    Java 控制台程序输出计时器代码
    网页出现“繁体字”?
    html5中video视频只有声音没有图像
    Clipboard 剪辑板
    区分window8中 ie10 window phone8
    void 0
    touch pointer
    全局作用域 eval
  • 原文地址:https://www.cnblogs.com/riwang/p/12556416.html
Copyright © 2011-2022 走看看