关于CORS(跨域资源共享)的几个http请求头小实验

时间:2023-03-09 09:40:32
关于CORS(跨域资源共享)的几个http请求头小实验

对几种与跨域相关的请求头做一个总结

关于跨域可以看:9 种常见的前端跨域解决方案(详解)

看完后可以配合我的代码做些实验,看看注释掉某个响应头会发生什么,整体代码会在最后贴出

关于CORS(跨域资源共享)的几个http请求头小实验


1. 跨域简单请求

需要在服务器响应头中加 Access-Control-Allow-Origin

2. 跨域复杂请求

这时候会发送预检请求options,服务器需要在响应头中添加Access-Control-Allow-Headers来表明支持的请求头

关于CORS(跨域资源共享)的几个http请求头小实验

需要响应头

  • 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);