什么是跨域

  • 由于浏览器的同源策略限制,当一个请求url协议、域名、端口三者之间任意一个与当前页面url不同时,需要跨域才能成功访问;

  • 同源策略是浏览器的行为,是浏览器最核心也最基本的安全功能

前端解决跨域方法

其实跨域问题都是找后端解决的;

误区:前端通过jsonp解决跨域

原生写法

1
2
3
4
5
6
7
8
9
10
1.创建一个script标签
var os=document.createElement("script")
2.给script一个src,src就是地址
os.src="http://suggestion.baidu.com/su?cb=qwer&wd=123"
3.将script插入到页面
document.body.appendChild(os)
4.回调函数处理数据
function qwer(d){
//d就是后端返回的数据
}

ajax请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$.ajax({
url:"http://suggestion.baidu.com/su?",
type:"get",
dataType:"jsonp",
data:{
wd:"123"
},
jsonp:"cb",// 回调参数key
jsonpCallback:"test",// 回调函数value
success:function(res){
console.log(res)
},
error:function(){
console.log("error")
}
})

jsonp

jsonp实现原理

  • 动态生成script标签,通过src属性来加载;

  • 默认使用Jsonp进行跨域时,请求的url地址后面会自动带上一个callback=xxx传给后端,后端需要对返回给前端的json数据做处理,此处的callback可通过jsonp来自定义,xxx可通过jsonpCallback来自定义;

  • jsonp: 回调函数的参数,是与后端约定好的参数,必须与后端保持一致。不另外定义jsonp的话,一般默认为jsonp:'callback'

  • jsonpCallback: 回调函数名,用来包裹住json数据,不另外定义的话,这个参数的值往往是随机生成的。

  • 按照上面百度搜索的jsonp来举例子:http://suggestion.baidu.com/su?cb=test;其中?cb=test中的cbkeytestvalue

  • 前端会传递一个callback参数(key)给后端,接着后端返回数据时会将这个callback参数的值(value)作为函数名来包裹住json数据,最终返给前端的就是一段js代码了;

  • 客户端需要将函数名称传递到服务器 可以如下实现:

1
2
3
4
5
6
7
8
//前端
<script>
function fn(data) {
console.log("客户端的函数调用了")
console.log(data)
}
</script>
<script src="http://localhost:3000/test?callback=fn"></script>
1
2
3
4
5
6
7
//后端
//路由配置
app.get("/test",(req,res)=>{
var fnName = req.query.callback;
var result = fnName + '({name:"zhangsan"})';
res.send(result);
})

结论

  1. jsonp方法的实现是需要前端和后端配合的;
  2. jsonp只支持get请求,不支持post请求;
  3. jsonp有安全性问题:jsonp劫持,jsonp劫持属于CSRF漏洞;

前端通过代理解决跨域

反向代理有很多,可以用nodejs,可以用nginx,这里只介绍nginx

nginx 反向代理

由于同源策略是浏览器导致的;所以可以找一个中间代理服务器;使用这个中间代理服务器去请求后端的地址;因为服务和服务之间是不存在同源策略的,所以中间代理服务器可以请求到后端接口数据;最后前端请求中间代理服务器;

1
2
3
4
//常用命令
start nginx 开启
nginx -s stop 停止
nginx -s reload 重新加载
  1. 官网下载稳定版
1
http://nginx.org/en/download.html

nginx

  1. 在根目录下,输入cmd打开终端

nginx

  1. 在终端中使用指令start nginx开启nginx
  2. 在浏览器输入localhost,出现如下界面即代表开启成功

nginx

  1. 配置nginx :nginx.conf里面配置

后端的 ip +后端口 之后 最后必须有 /,而且最后的最后必须要带上;

nginx

如果不带; nginx命令会不生效;

nginx

如果不带 / ;接口地址为404;

nginx

  1. 修改前端的请求接口

nginx

  1. 将前端文件放到nginx文件的html目录下(也可以不放,见下文的补充)

nginx

  1. 重新加载一下nginx -s reload,然后在浏览器输入 localhost/myDemo.html

nginx

未经过反向代理的接口为:

nginx

补充

上面第7步中,也可以不将前端文件放到nginx文件的html目录下

  1. 项目通过vsCode插件Live Server起一个本地服务,地址是127.0.0.1:5500然后这个服务就不能关掉了,当然页面可以关;

nginx

  1. 修改nginx的配置文件

nginx

  1. 重新加载一下nginx -s reload,然后在浏览器输入 localhost/myDemo.html

nginx

参考文献

关于Jsonp跨域,你知道多少?

jsonp解决跨域问题(简单易懂)

jsonp劫持

前端解决跨域,nginx 反向代理

正确的Nginx跨域配置

前端本地开发如何靠自己解决跨域