前言:
其实跨域的出现主要是因为浏览器的同源策略导致的,那什么又是浏览器的同源策略呢???。
同源策略
概念:协议,域名,端口 3者相同就是同源,
反之3者中有一个不同, 则是不同源 【不同源接口请求,就会出现跨域】
作用:浏览器的同源策略主要是为了保证用户信息的安全而出现。
那什么情况下属于同源,什么情况下是不同源呢,看下图
在这里注意一下啊,这里是为了突出端口的区别才写上端口。
在默认情况下 http 可以省略端口 80, https 省略 443。
这别到时候闹笑话了,你和我说 http://www.example.com:80 和 http://www.example.com 不是同源,他俩是一个东西。
http://www.example.com:80 === http://www.example.com
https://www.example.com:443 === https://www.example.com
解决方案---JSONP
JSONP
是 JSON with Padding
的简称 ,是一种较为常用的解决跨域访问的方式。
jsonp 解决跨域问题的本质:就是利用 script 标签的 src 属性来进行,由于script标签的src属性不受跨域的限制,
所以我们可以将我们要请求的 服务器地址及相关参数 作为 src的值 来进行传输,然后再由后台进行配合就可以实现跨域。
我们先来看一段示例代码:
ajax({//此ajax方法是封装了XMLHttpRequest对象实现,具体代码与本文无关就不贴了
method : 'get',
url : 'http://127.0.0.1:8787',
data : {
'name' : '小明',//此ajax方法会自动将数据以get方式提交
'age' : 22
},
success : function (message) {
alert(message);
},
async : true
})
上面的代码很简单,浏览器端发起了一个异步ajax请求,让我们来看看服务端代码:
app.get('*', function(req, res) {//这里只截取了关键代码
res.send("测试数据");
});
不出所料,浏览器甩了我一脸...
不要担心,我们重振旗鼓再战!JSONP 炸裂炫酷出场~
步骤1:
1: 在客户端全局作用域下定义函数showJsonp,作为后端返回给我们函数的调用,
如果这个函数不是全局的话,我们在调用的时候会报错,而且这个一定要在前面。
2: 将 不同源的服务器端请求 地址写在 script 标签的 src 属性中,
---------------js里面
// 在全局作用域下定义回调函数showJsonp
function showJsonp(obj){
console.log(obj.message);
}
var url = 'http://127.0.0.1:8787/?msg=hello&cb=showJsonp' // cb参数名为showJsonp
var script = document.createElement('script');
script.setAttribute('src',url);
script.setAttribute('type','text/javascript');
document.getElementsByTagName('head')[0].appendChild(script);
// script.src = url
// document.body.appendChild(script);
// script.onload = function () {
// document.body.removeChild(script)
// }
------------或者直接在html里面写
<body>
<script>
function fn(data){
console.log(data.message);
console.log("ok函数调用了")
}
</script>
<script src="http://127.0.0.1:8787/test?msg=hello&cb=showJsonp"></script>
</body>
<script src="https://cdn.bootcss.com/jquery/3.5.0/jquery.min.js"></script><script>
$.ajax({
url: "http://localhost:8080/api/jsonp",
dataType: "jsonp",
type: "get",
data: {
msg: "hello"
},
jsonp: "cb",
success: function(data) {
console.log(data);
}
});
</script>
再来看看后台代码~
3: 服务器端响应的必须是一个函数的调用,真正要发送给客户端的数据要作为函数调用的参数
app.get('*', function(req, res) {
// let callback = req.query.cb;
let { cb, msg } = req.query;
let content = cb + "({'message':'测试数据2', 'say': JSON.stringify(msg)})";
res.send(content);
});
结果
大!获!全!胜!
我们来分析一波战术策略了~
在平常写代码的时候,可能很多人没有注意,浏览器对于script,iframe等标签的 src 等属性,是 没有 同源策略 限制 的。
而 jsonp 就很好的利用了这一点~,在我们发起请求时,url 后跟了一个名为 func
的参数,而这个 参数 就是之后需要用到的 回调函数名称。
我们通过动态插入 script
标签的方式,利用 script 标签的 src 属性发起请求,浏览器就不会以同源策略来找事了.......完美!!
而后台根据请求构造出的数据长啥样呢?
showJsonp({'message':'测试数据2'})
告诉我!这段代码插入你的 script 标签内后,会发生啥?!
当然是执行早就定义好的 showJsonp 函数 啊~
bingo,完美解决跨域问题~~
最后
jsonp 的方式兼容性非常好,即便是那些老古董浏览器,也可以用 jsonp 的方式解决跨域问题,
但是它也有所限制,它只能使用 get 方式发起请求,
并且对于不同域名之间页面的 js 互相调用无能为力
注意的是:利用该方法实现是需要 前端 和 后端 配合的。
如果前端要连接传统后台服务器-----【接口跨域】
分部署时的跨域方案和调试时的跨域方案,具体见下:
一:部署时的跨域方案
方案1: 最省事的 将前端代码 和 后端接口部署在同域的web服务器上
方案2: 由后台服务器配置策略,设为允许跨域访问
二:调试时的跨域解决方案
1: 使用HBuilderX(专为vue打造的编译器)内置浏览器
2: 使用 webapck-dev-server 配置代理
module.exports ={
devServer: {
// proxy属性:用来添加代理服务配置的,每一个属性,就是一个代理规则的配置
"proxy": {
"/prefix/api/user/list": {
"target": "https://api-remote.xxxx.com",
"pathRewrite": {
"^/prefix": ""
}
}
}
}
}
-------修改前端接口请求方式,改为不带域名。(因为现在是同域请求了)
<button id="getlist">获取列表</button>
<button id="login">登录</button>
<script src="https://cdn.bootcss.com/axios/0.19.2/axios.min.js"></script>
<script>
axios.defaults.withCredentials = true;
getlist.onclick = () => {
axios.get("/api/corslist").then(res => {
console.log(res.data);
});
};
login.onclick = () => {
axios.post("/api/login");
};
</script>
前端开发如何独立解决跨域问题 ----->【charles(类似fiddler)正向代理 和 nginx反向代理】
3: 给浏览器安装插件,禁止浏览器报跨域
前言:
当我们本地服务器预览页面时,是直接通过本地IP地址去访问开发中的页面,同时这个页面会调一些现有的接口时,就面临着跨域的问题。
比如:本地预览的地址是:http://localhost:8080/,访问的接口地址是http://dcloud.io/api
如果仅仅是为了 本地预览,可以使用 Chrome浏览器插件 来协助调试,本插件只能解决简单请求的跨域调试(点击搜索什么是简单请求),对于非简单请求的OPTION预检(点击搜索什么是预检请求)以及线上服务器也有跨域需求的用户,可以服务端配合解决。
Chrome插件名称:Allow-Control-Allow-Origin: *
安装方式:
- 在线安装
使用谷歌浏览器直接打开插件地址https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi安装即可 - 离线安装
国内用户如果无法在线安装,可在本页面底部下载附件,离线安装- 下载得到: Allow-Control-Allow-Origin.crx
- 点击浏览器右上角的菜单按钮打开谷歌浏览器的扩展管理页面
- 将下载的扩展插件拖入扩展管理页面
使用方式
- 打开待调试的页面
- 在扩展栏目找到安装的插件,点击打开插件配置
- 输入想要进行跨域调试的接口的地址,点击添加即可
注意事项
- 此插件适合本地调试使用,线上部署如果和接口不同域还需要服务端配合。
- 如果实际响应的内容与浏览器预期的内容有差异还可能被CORB策略所阻止。
firefox跨域插件