携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情
故事背景
昨天温习了一下跨域问题,因为自己做demo,怎么写就怎么对,处理跨域问题真实信手拈来,so 一贼,可能是生活看不惯嚣张跋扈的人,于是下午后端老表就来找我联调一个接口。 因为系统要做海外环境还有一些乱七八糟的环境,现在前端要在当前环境,请求不同环境(不同环境不同域名)请求数据,我看了一下,这个复杂了,复杂请求发送了options请求,你要处理一下options请求,设置允许跨域的一系列响应头
"Access-Control-Allow-Origin": req.headers.origin||req.headers.referer,
"Access-Control-Allow-Methods": "POST",
'Access-Control-Allow-Headers': ["xxx"],
"Access-Control-Allow-Credentials": true
中间太多曲折,但是因为他本地启动的是http服务,我在https里请求,所以一直进不到他的断点。这个问题忽略,纯人为造成的,跳过这个问题, options请求处理完,果然可以请求成功了,但是结果还是不如预期,因为sesssion鉴权存在cookie里,所以请求要携带cookie,否则就会被重定向。
我以为,这些都是意料之中
axios请求跨域携带cookie设置
axios.defaults.withCredentials = true;
这个我真知道,网上搜索也一搜就有,所以这个早就配了,后端配置响应header"Access-Control-Allow-Credentials": true,也配了。但是请求头里迟迟不见cookie的身影,我懵了,说的贼好听,跨域请求携带cookie,真的就能带cookie吗?实际是不可以的,
optons请求是哪里来的,这个没有异议,复杂请求会先发送一个OPTIONS请求,就是探探虚实,看看服务器,允许当前请求访问不, xhr请求分为简单请求复杂请求, 满足下面两个条件就是简单请求
1.请求方法是以下三种方法之一:
HEAD GET POST
2.HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值:application/x-www-form-urlencoded、multipart/form-data、text/plain
发现问题1
axios这个库不简单,当没有发送数据时,自动过滤了中headers: { "Content-Type": "application/json", },避免了一个简单请求,因为用户错误操作,变成一个复杂请求,避免一次不必要的预检请求
index.html 用live-server启动,端口5500
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body></body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.27.2/axios.min.js"></script>
<script>
axios.defaults.withCredentials = true;
axios({
url: "http://localhost:5501/data",
method: "POST",
headers: {
"Content-Type": "application/json",
},
}).then((res) => {
console.log(res);
});
fetch("http://localhost:5501/data", {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
})
.then((response) => response.json())
.then((res) => {
console.log(res);
});
</script>
</html>
node.js ./server.js
const fs = require('fs');
const http = require('http');
const server = http.createServer(async (req, res) => {
const {
url,
method,
} = req;
let data = null;
if (url == "/data" && method == "POST" || url == '/data' && method == "OPTIONS")
switch (url) {
case '/data':
data = `{
"name":"tom",
"age":19
}`
res.writeHead(200, {
"Access-Control-Allow-Methods": "POST",
"Access-Control-Allow-Credentials": true,
"Access-Control-Allow-Origin": "http://127.0.0.1:5500",
"Access-Control-Allow-Headers": 'Content-Type'
});
break;
}
res.end(data);
})
server.listen('5501', () => {
console.log('http://localhost:5501')
})
小小的关怀,大大的感动,对axios说声感谢,可能还有其他优化,这里也不测试,也不研究了。毕竟是锦上添花的东西 请求头里没有content-type,所以是简单请求,没有预检请求
如果axios加了data
axios({
url: "http://localhost:5501/data",
method: "POST",
data:{
name:"xx"
},
headers: {
"Content-Type": "application/json",
},
}).then((res) => {
console.log(res);
});
就真的是复杂请求了,没法优化了
重点来了 生产中跨域请求不可以携带cookie,暂时没有解决办法,chrome安全机制
携带cookie了吗?并没有。chrome不可以
Safari可以携带cookie,也没有预检请求
当前的url,请求另一个url不可携带cookie,cookie是按domain区分的,也就是按域名区分,如果把请求的url中loaclhost改成127.0.0.1,就可以携带cookie