什么是跨域?
同源策略:同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,由客户端访问某一个服务器的文件时,如果发起请求的这个来源与进行响应的目标的源不一致,目标源出于安全的角度,将拒绝这次访问。
同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
比如,我们网站想从别人网站中拿一些数据,那么默认的时候,别人网站是不会给我们数据的。
协议名、域名、端口,这三项都相同,则被称为同源。三项中只要有一项不同,则被称为跨源。
协议名指http、https等这种域名包含网站域名、ip地址、计算机名称端口默认是80,80并不会显示在浏览器地址栏中
# 下面哪组网址跨源(跨域)了?
http://127.0.0.1/1.html http://127.0.0.1/2.html
http://127.0.0.1:80/1.html http://127.0.0.1
http://127.0.0.1/ http://localhost/
http://localhost:81/1.html http://localhost:82/1.html
http://abc.com/ http://mp3.abc.com/
http://mp3.abc.com/ https://mp3.abc.com/
跨源访问也叫做跨域访问。
真实开发中,很多场景下会涉及到跨域访问,比如百度网站就特别大,其中有mp3.baidu.com、image.baidu.com、tieba.baidu.com等等,而其中一些数据或服务是需要共用的,所以就需要跨域访问。
再比如支付系统,各个电商网站都提供支付宝或微信付款,这个就需要用到支付宝或微信的接口,所以这也是跨域访问。
如何解决跨域问题
一、jsonp
JSONP是什么
JSONP(JSON with Padding),是一个非官方的跨域解决方案,纯粹凭借程序员的聪明才智开发出来,只支持get请求。
JSONP怎么工作的?
在网页有一些标签天生具有跨域能力,比如:img link iframe script。
JSONP就是利用script标签的跨域能力来发送请求的。
JSONP的使用
1.动态的创建一个script标签
var script = document.createElement("script");
2.设置script的src,设置回调函数
script.src = "http://localhost:3000/testAJAX?callback=abc";
function abc(data) {
alert(data.name);
};
-3.将script添加到body中
document.head.appendChild(script);
服务器中路由的处理
router.get("/testAJAX" , function (req , res) {
console.log("收到请求");
var callback = req.query.callback;
var obj = {
name:"张三",
age:18
}
res.send(callback+"("+JSON.stringify(obj)+")");
});
jq中的jsonp
$.ajax({
url:"/jsonp",
dataType:"jsonp", // 类型为jsonp
jsonp:"cb", // 指定回调位cb
data:{ // 携带的参数
a:1,
b:2
},
success(res){ // 返还的值
console.log(res);
}
})
二、CORS
CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持get和post请求。
CORS怎么工作的?
CORS是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行。
CORS的使用
主要是服务器端的设置:
res.setHeader("Access-Control-Allow-Origin","*")
三、服务器代理
由于浏览器有同源策略限制,所以想要跨域访问其他域下的资源,需要绕开浏览器的这个限制,可以在服务器端设置一个代理,由服务器端向跨域下的网站发出请求,再将请求结果返回给前端,成功避免同源策略的限制。
具体实现
安装 http-proxy-middleware : npm i http-proxy-middleware
配置 http-proxy-middleware
const {createProxyMiddleware} = require("http-proxy-middleware");
app.use("/api",createProxyMiddleware({
target:"http://localhost:4000",
pathRewrite: {
'^/api' : '', // 重写请求,比如我们源访问的是api/list,那么请求会被解析为/list
}
}))