什么是跨域?
跨域指的是浏览器不能访问其他浏览器的网站脚本,
是由浏览器的同源策略造成的,是浏览器对javascript实施的安全限制;
什么是同源策略,同源策略是一种约定,他也是浏览器最为核心也是最基本的安全功能,他能帮助切阻挡恶意文档的攻击
协议,域名,端口号三者必须相同,称之为同源,如果有一个不相同,则就会收到同源策略的限制,就造成了跨域;
三种跨域解决办法;
一 使用cors | 请求头解决跨域; cross-origin resource sharing 跨域资源共享
使用cors模块;
1 在服务端使用cors模块解决跨域,最简单暴力的解决方式,将所有的api都设置成共享资源;
使用方法:引入cors模块,在 使用app.use(cors()) 不推荐,因为所有的api全部暴露,
2 使用cors模块单独一个或多个接口可以跨域访问;
可以在处理函数第二个参数添加cors() 解决跨域;
app.get("/",cors(),function())
不适用cors模块;
3 使用设置响应头解决跨域
原理 设置请求头 允许所有请求源跨域访问一个接口;
req.headers.origin //获取请求源
res.header(“Access-Control-Allow-Origin”,req.headers.origin) //设置请求源可以访问本接口;
res.header(“Access-Control-Allow-Origin”,"*") //设置请求源可以访问本接口; * 代表允许所有跨域请求访问;
4 设置黑白名单;
将可以进行访问的请求源存放到一个数据|数据库中进行保存,在获取请求源是否在可以进行访问的数据里面,如果有,则在白名单中,可以进行访问,
在设置响应头的 res.setHeader(“Access-Control-Allow-Origin”,“本次请求的请求源”);
二 使用jsonp 解决跨域;
原理,利用script标签src属性不存在跨域的特性,向服务器发送一个回调函数,服务器将数据包裹在回调函数之中,获取响应的数剧;
发送jsonp请求
function f1(data) {
console.log(data);
}
$(“button”).click(function () {
$("").appendTo(“body”)
})
当body直接添加script标签,标签会立即加载,并请求数据,次数据并不会跨域;
服务端 响应数据 通过获取的请求参数回调函数,将数据返回到script标签,返回成函数调用的方式调用数据;
返回给客户端的数据是函数调用的格式 f1(),把响应数据作为参数写进f1(data);
也可以使用res.jsonp({}) 方式直接返回数据;
app.get("/",function(req,res){
var data={
code:200
}
res.send(`${req.query.callback}(${JSON.stringify(data)})`);
})
这种方法会产生script标签,在页面中 不推荐;
使用juqery的ajax请求
$.ajax({
type: "GET",
url: "http://127.0.0.1:3000/?callback=f1",
dataType: "JSONP",
success: function (res) {
console.log(res);
}
})
只需要将dataType:“jsonp” 服务端使用res.json() 响应数据,就可以解决跨域;
三 使用代理服务器
代理服务器 我们向不存在跨域的代理服务器发送请求,让服务器代理发送我们的请求发送到我们存在跨域的服务器上,代替我们进行请求数据,
然后将请求到的数据返回到前端,就解决了跨域的问题;
请求 我们将地址写成本地服务器,将后面的请求参数最前面加上我们的代理服务器上,并在请求参数加上一个路径前缀如
https://www.baidu.com/?age=30 跨域的请求
http://127.0.0.1:3000/api/?age=30 向代理服务器发送的请求; 前缀为/api/
http-proxy-middleware 使用代理服务器中间件;
var proxy=require("http-proxy-middleware");
proxy.createProxyMiddleware({
target:"https://www.baidu.com" //目标服务器的网站;
secure:false //如果是https ,需要将此配置设置为false;
pathRewrite:{ //路径重写,需要将路径添加的前缀删除;
"^/api":""
}
changeOrigin:true //是否需要修改源;
ws:true , ws :websocket,套接字,支持双通信的网络的协议, 是否支持websocket 可以不配置
})
最后再将proxy应用到app中
app.use(proxy);