跨域问题是因为什么引起的?是因为浏览器的同源策略
什么是浏览器的同源策略
协议、端口、主机名,完全相同。浏览器不允许使用非同源的数据
同源策略是指:若页面的源和页面运行过程中加载的源不一致时,出于安全考虑,浏览器会对跨域的资源访问进行一些限制
如上图,如果我在百度的站点,通过fetch方法来访问掘金的网页地址的时候,这时候控制台报了错:
Access to fetch at 'https://juejin.cn/' from origin 'https://www.baidu.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
这个时候意味着出现了跨域问题。也就是说百度网页跨域访问了掘金,源地址是www.baidu.com/,目标地址是:http…
跨域问题的处理方案
既然是浏览器引起的,那么其实我们只要想办法绕过浏览器访问跨域的url,就不会被拒绝。于是我们可以想到通过代理服务器、nginx等。
proxy代理
对于前端开发而言,大部分的跨域问题,都是通过代理解决的
代理适用的场景是:生产环境不发生跨域,但开发环境发生跨域
原理:
- 前端应用将原本需要跨域访问的请求发送给自身的代理服务器
- 代理服务器再将请求转发至实际的目标服务器,并从目标服务器获取数据
- 最后将数据返回给前端应用。
在实际开发中,只需要对开发服务器增加配置即可
// vue 的开发服务器代理配置,react项目同理
// vue.config.js
module.exports = {
devServer: { // 配置开发服务器
proxy: { // 配置代理
"/api": { // 若请求路径以 /api 开头
target: "http://dev.taobao.com", // 将其转发到 http://dev.taobao.com
},
},
},
};
CORS
此方案需要后端的配合。
CORS是基于http1.1的一种跨域解决方案,它的全称是Cross-Origin Resource Sharing,跨域资源共享。
它的总体思路是:如果浏览器要跨域访问服务器的资源,需要获得服务器的允许
服务器允许的方式是:当服务器收到请求后,如果允许该请求跨域访问,需要在响应头中添加Access-Control-Allow-Origin字段
该字段的值可以是:
- *:表示什么人我都允许访问
- 具体的源:比如
http://my.com,表示我就允许你访问
其实针对不同的请求(根据对服务器造成不同程度的影响),CORS 规定了三种不同的交互模式,分别是:
- 简单请求
- 需要预检的请求
- 附带身份凭证的请求
这三种模式从上到下层层递进,请求可以做的事越来越多,要求也越来越严格。
// 后端代码 nodejs
const allowOrigins = ["http://127.0.0.1:5500", "null"];
module.exports = function (req, res, next) {
// 1. 处理简单请求
if ("origin" in req.headers && allowOrigins.includes(req.headers.origin)) {
res.header("access-control-allow-origin", req.headers.origin);
}
// 2. 处理预检请求
// if (req.method === "OPTIONS") {
// console.log("这是一个预检请求");
// res.header("access-control-allow-origin", req.headers.origin);
// res.header(
// "Access-Control-Allow-Methods",
// req.headers["access-control-request-method"]
// );
// res.header(
// "Access-Control-Allow-Headers",
// req.headers["access-control-request-headers"]
// );
// }
// 3. 附带身份凭证的请求
// res.header("Access-Control-Allow-Credentials", true); // 允许cookie
next();
};
JSONP
JSONP缺点,只能支持GET请求
JSONP的做法是:当需要跨域请求时,不使用AJAX,转而生成一个script元素去请求服务器,由于浏览器并不阻止script元素的请求,这样请求可以到达服务器。服务器拿到请求后,响应一段JS代码,这段代码实际上是一个函数调用,调用的是客户端预先生成好的函数,并把浏览器需要的数据作为参数传递到函数中,从而间接的把数据传递给客户端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JSONP Example</title>
<script>
// 定义回调函数
function jsonpCallback(data) {
console.log('Received data:', data);
// 处理数据
document.body.innerHTML += `<p>${data.name}: ${data.message}</p>`;
}
// 创建<script>标签并添加到页面中
function createScript() {
const script = document.createElement('script');
script.src = `http://localhost:3000/?callback=jsonpCallback`; // 服务端URL和回调函数名
document.head.appendChild(script);
}
// 页面加载完成后创建<script>标签
window.onload = createScript;
</script>
</head>
<body>
<h1>JSONP Example</h1>
</body>
</html>