跨域解决方案
跨域(非同源策略请求)
同源策略:
同源策略是浏览器的一个安全限制,‘协议,域名,端口’,三个都相同即为同源 其中一个不同即为非同源,非同源下三种行为受到限制:cookie无法获取,dom无法获取,ajax请求无效
跨域:
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
跨域的几种解决方案:
JSONP 实现跨域
JSONP
是使用方法回调的原理,script
不存在跨域请求的限制,引入其他网页的 js,这个页面的 js 可以调用你网页的代码
缺点:JSONP 需要服务端支持,且只支持 GET 请求,安全性也不好
客户端借助 script
标签请求服务端的一个地址,服务端返回一段带有调用某个全局函数调用的 js脚本,将需要返回给客户端的数据通过参数传递给这个函数,函数中就可以得到返回的数据
客户端:(http://127.0.0.1:3000)
js 实现 JSONP 跨域:
<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 跨域:
$.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)
//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
//原生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
//设置响应头的中间件
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:
module.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)
//打开指定源
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)
//监听客户端发来的消息
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)
//连接服务端
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)
//监听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:
<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:
//不需要代码
服务端:(http://127.0.0.1:4000)
B.html:
//定义window.name的内容
window.name = 'a'
nginx 反向代理
Nginx
(engine x) 是一个高性能的HTTP和反向代理web服务器,可以实现反向代理 同源策略是浏览器遵循的标准,客户端将请求发给代理服务器,代理服务器再向后端服务器发请求就可以解决跨域的问题 配置 nginx 配置文件 nginx.conf
nginx.conf:
http{
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
}
}
}
原文始发于微信公众号(前端24):跨域解决方案
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/217128.html