跨域解决方案
跨域(非同源策略请求)
同源策略:
同源策略是浏览器的一个安全限制,‘协议,域名,端口’,三个都相同即为同源
其中一个不同即为非同源,非同源下三种行为受到限制:cookie无法获取,dom无法获取,ajax请求无效
跨域:
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
跨域的几种解决方案:
JSONP 实现跨域
JSONP
是使用方法回调的原理,script
不存在跨域请求的限制,引入其他网页的 js,这个页面的 js 可以调用你网页的代码
缺点:JSONP 需要服务端支持,且只支持 GET 请求,安全性也不好
客户端借助 script
标签请求服务端的一个地址,服务端返回一段带有调用某个全局函数调用的 js脚本,将需要返回给客户端的数据通过参数传递给这个函数,函数中就可以得到返回的数据
客户端:(http://127.0.0.1:3000)
js 实现 JSONP 跨域:
1
2
3
4
5
6
7
8
9<script> //定义fn函数接收服务端返回的数据 function fn(data) { console.log(data) //{a: 1, b: 2} } </script> <!-- 通过script的src属性,请求http://127.0.0.1:4000中的getData接口并携带callback参数,指定回调函数的名字 --> <script src="http://127.0.0.1:4000/getData?callback=fn"></script>
jquery 封装的 ajax 实现 JSONP 跨域:
1
2
3
4
5
6
7
8
9
10$.ajax({ url: 'http://127.0.0.1:4000/getData', methods: 'get', dataType: 'jsonp', //设置执行JSONP请求 jsonpCallback: 'fn', //设置回调函数名字 success: res => { console.log(res) //{a: 1, b: 2} } })
服务端:(http://127.0.0.1:4000)
1
2
3
4
5
6
7
8
9
10
11//getData接口 app.get('/getData', (req, res) => { let data = { a: 1, b: 2 }; let fn = req.query.callback; //调用fn函数传递data数据 res.send(fn + '(' + JSON.stringify(data) + ')'); });
CORS 跨域资源共享
CORS
(Cross-Origin Resource Sharing 跨域资源共享)是一个W3C标准,是一种网络浏览器的技术规范,服务端使用额外的 HTTP 头来告诉浏览器,让运行在一个 origin (domain) 上的 Web 应用被准许访问来自不同源服务器上的指定的资源
客户端:(http://127.0.0.1:3000)
需要配置是否携带 cookie:withCredentials: true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29//原生js var xhr = new XMLHttpRequest() xhr.open("get","http://127.0.0.1:4000",true) xhr.withCredentials = true; xhr.send() xhr.onload = function(){ console.log(xhr.response) } //JQuery $.ajax({ url : 'http://127.0.0.1:40006', method: 'get' xhrFields: { withCredentials: true }, success : function(data) { console.log(data); } }); //axios axios('http://127.0.0.1:4000', { method: 'get', withCredentials: true, }).then(data => { console.log(data); }).catch(err => { console.log(err); });
服务端:(http://127.0.0.1:4000)
普通跨域请求只需服务器端设置 Access-Control-Allow-Origin
1
2
3
4
5
6
7
8
9
10
11
12
13//设置响应头的中间件 app.use((req, res, next) => { //设置允许指定源访问(* 表示允许所有源访问,此时不能允许携带cookie) res.header('Access-Control-Allow-Origin', 'http://127.0.0.1:3000'); //设置允许指定HTTP请求方法访问 res.header('Access-Control-Allow-Methons', 'GET,POST'); //设置允许跨域访问携带cookie(此时允许跨域访问的源不能为 *,需要指定具体的源) res.header('Access-Control-Allow-Credentials', true); //设置允许跨域访问的请求头 res.header('Access-Control-Allow-Headers', 'Content_Type, Content-Length, Authorization, X-Requested-With, Accept'); next(); })
http proxy 代理实现跨域请求
使用 webpack 的 webpack-dev-server 开发插件中的 http-proxy-middleware来实现跨域代理
客户端:
webpack.config.js:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16module.exports = { devServer: { port: 3000, progress: true, contentBase: './build', proxy: { '/getData': { //需要跨域的源 target: 'http://127.0.0.1:4000', //允许改变请求源为target changeOrigin: true } } } }
postMessage 实现跨源通信
postMessage
是 html5 新增的一个解决跨域的一个方法,postMessage() 方法允许来自不同源的脚本采用异步方式进行有限的通信,可以安全地实现跨文本档、多窗口、跨域消息传递
客户端:(http://127.0.0.1:3000)
1
2
3
4
5
6
7
8
9//打开指定源 let open = window.open('http://127.0.0.1:4000'); //发送消息到指定源(服务端) open.postMessage('a', 'http://127.0.0.1:4000'); //监听服务端发来的消息 window.addEventListener('message', funciton(event) { console.log(event.data) //ab }, false)
服务端:(http://127.0.0.1:4000)
1
2
3
4
5
6
7//监听客户端发来的消息 window.addEventListener('message', funciton(event) { console.log(event.data) //a //发送消息到客户端 event.source.postMessage(event.data + 'b') }, false)
webScoket 实现跨源通信
webSocket
是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
webSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,进行数据互相传送
Socket.IO
是一个基于 webSocket 封装的库,包括了客户端的js和服务器端的nodejs,它的目标是构建可以在不同浏览器和移动设备上使用的实时应用
客户端:(http://127.0.0.1:3000)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16//连接服务端 let socket = io('http://127.0.0.1:4000'); //连接成功处理 socket.on('connect', function() { //监听服务端消息 socket.on('message', function(msg) { console.log(msg) //ab }); //监听服务端连接关闭 socket.on('disconnect', function() { console.log('服务端连接关闭') }); }); //向服务端发送消息 socket.send('a');
服务端:(http://127.0.0.1:4000)
1
2
3
4
5
6
7
8
9
10
11
12
13
14//监听socket连接(server是服务器创建的服务) socket.listen(server).on('connection', function(client) { //监听客户端消息 client.on('message', function(msg) { console.log(msg) //a //向客户端发送消息 client.send(msg + 'b') }); //监听客户端连接关闭 client.on('disconnect', function() { console.log('客户端连接关闭') }); });
window.name 实现跨域
window.name
属性可设置或返回存放窗口的名称的一个字符串,每个窗口都有独立的 window.name,窗口载入的所有页面共享一个 window.name
客户端:(http://127.0.0.1:3000)
A.html:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<iframe src="http://127.0.0.1:4000/B.html" style="display: none;"></iframe> <script> let count = 0; iframe.onload = function() { //判断count,只执行一次 if(count === 0) { //需要先把地址指向同源 iframe.src = 'http://127.0.0.1:3000/C.html'; count++; return; } console.log(iframe.contentWindow.name) //a } </script>
C.html:
1
2//不需要代码
服务端:(http://127.0.0.1:4000)
B.html:
1
2
3//定义window.name的内容 window.name = 'a'
nginx 反向代理
Nginx
(engine x) 是一个高性能的HTTP和反向代理web服务器,可以实现反向代理
同源策略是浏览器遵循的标准,客户端将请求发给代理服务器,代理服务器再向后端服务器发请求就可以解决跨域的问题
配置 nginx 配置文件 nginx.conf
nginx.conf:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16http{ server{ listen 4000; #端口号 server_name http://127.0.0.1; #主机域名 //反向代理配置 location /getData { proxy_pass http://127.0.0.1:3000; #反向代理主机地址配置 proxy_set_header X-real-ip $remote_addr; #设置代理请求头,将用户访问的IP记录到自己的IP地段上 proxy_set_header Host $http_host; #设置代理请求头,将用户访问的地址记录到自己的HOST记录上 proxy_connect_timeout 60; #代理连接超时时间,默认为60 proxy_send_timeout 60; #代理发送超时时间,默认为60 proxy_read_timeout 60; #代理接受超时时间,默认为60 } } }
最后
以上就是落后太阳最近收集整理的关于跨域解决方案跨域解决方案的全部内容,更多相关跨域解决方案跨域解决方案内容请搜索靠谱客的其他文章。
发表评论 取消回复