如何解决跨域问题???
一、为什么会出现跨域问题呢? 首先了解一下同源策略(SOP),它是由Netscape公司在1995年引入浏览器的。同源策略是浏览器中最基本最重要的安全功能,如果缺少了同源策略,我们的浏览器就会很容易受到XSS、CSFR等攻击。而所谓的同源策略是指:协议+域名+端口三者相同。 因此,当我们请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。 例如:
二、解决跨域问题的方法(重点!!!) 1、通过JSONP跨域 JSONP 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求。 核心思想:网页通过添加一个script元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。
第一种,原生实现:
<script src="http://test.com/data.php?callback=dosomething"></script>
<script type="text/javascript">
function dosomething(res){
console.log(res.data)
}
</script>
第二种,jQuery ajax实现:
$.ajax({
url: 'http://www.test.com:8080/login',
type: 'get',
dataType: 'jsonp',
jsonpCallback: "handleCallback",
data: {}
});
第三种,在Vue.js实现:
this.$http.jsonp('http://www.domain2.com:8080/login', {
params: {},
jsonp: 'handleCallback'
}).then((res) => {
console.log(res);
})
2、设置document.domain解决无法读取非同源网页的 Cookie问题 因为浏览器是通过document.domain属性来检查两个页面是否同源,因此只要通过设置相同的document.domain,两个页面就可以共享Cookie(此方案仅限主域相同,子域不同的跨域应用场景。)
document.domain = 'test.com';
3、CORS CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。
1、普通跨域请求:只需服务器端设置Access-Control-Allow-Origin 2、带cookie跨域请求:前后端都需要进行设置
需要注意的是,CORS跨域需要在前、后端同时设置!
【前端设置】根据xhr.withCredentials字段判断是否带有cookie。
第一种,原生ajax:
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.open('post', 'http://www.domain2.com:8080/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
第二种, jQuery ajax :
$.ajax({
url: 'http://www.test.com:8080/login',
type: 'get',
data: {},
xhrFields: {
withCredentials: true
},
crossDomain: true,
});
第三种,vue-resource:
Vue.http.options.credentials = true
第四种,axios :
axios.defaults.withCredentials = true
【服务端设置】服务器端对于CORS的支持,主要是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。
第一种,Java后台:
response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");
第二种,Nodejs后台:
var http = require('http');
var server = http.createServer();
var qs = require('querystring');
server.on('request', function(req, res) {
var postData = '';
req.addListener('data', function(chunk) {
postData += chunk;
});
req.addListener('end', function() {
postData = qs.parse(postData);
res.writeHead(200, {
'Access-Control-Allow-Credentials': 'true',
'Access-Control-Allow-Origin': 'http://www.domain1.com',
'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'
});
res.write(JSON.stringify(postData));
res.end();
});
});
server.listen('8080');
console.log('Server is running at port 8080...');
第三种,PHP后台:
<?php
header("Access-Control-Allow-Origin:*");
第四种,Apache需要使用mod_headers模块来激活HTTP头的设置,它默认是激活的。你只需要在Apache配置文件的, , 或的配置里加入以下内容即可:
Header set Access-Control-Allow-Origin *
4、webpack本地代理 在webpack.config.js中利用 WebpackDevServer 配置本地代理,详情配置查看devServer。
如下简单配置案例,这样 http://localhost:8080/api/getUser.php 的请求就是后端的接口 http://192.168.25.20:8088/getUser.php
devServer: {
port: 8080,
proxy: {
"/api": {
target: "http://192.168.25.20:8088"
}
}
}
5、websocket Websocket 是 HTML5 的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。WebSocket 和 HTTP 都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 服务器与 客户端都能主动向对方发送或接收数据。同时,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。
6、Nginx反向代理 Nginx 实现原理类似于 Node 中间件代理,需要你搭建一个中转 nginx 服务器,用于转发请求。
使用 nginx 反向代理实现跨域,是最简单的跨域方式。只需要修改 nginx 的配置即可解决跨域问题,支持所有浏览器,支持 session,不需要修改任何代码,并且不会影响服务器性能。
我们只需要配置nginx,在一个服务器上配置多个前缀来转发http/https请求到多个真实的服务器即可。这样,这个服务器上所有url都是相同的域 名、协议和端口。因此,对于浏览器来说,这些url都是同源的,没有跨域限制。而实际上,这些url实际上由物理服务器提供服务。这些服务器内的 javascript可以跨域调用所有这些服务器上的url。
先下载nginx,然后将 nginx 目录下的 nginx.conf 修改如下:
server {
#nginx监听所有localhost:8080端口收到的请求
listen 8080;
server_name localhost;
# Load configuration files for the default server block.
include /etc/nginx/default.d
7、跨文档通信 API:window.postMessage() 调用postMessage方法实现父窗口http://test1.com向子窗口http://test2.com发消息(子窗口同样可以通过该方法发送消息给父窗口)
它可用于解决以下方面的问题:
- 页面和其打开的新窗口的数据传递
- 多窗口之间消息传递
- 页面与嵌套的iframe消息传递
- 上面三个场景的跨域数据传递
var openWindow = window.open('http://test2.com', 'title');
openWindow.postMessage('Nice to meet you!', 'http://test2.com');
调用message事件,监听对方发送的消息
window.addEventListener('message', function (e) {
console.log(e.source);
console.log(e.origin);
console.log(e.data);
},false);
好啦,以上就是总结的七种常用的解决跨域问题的方法,希望对大家有所帮助,别忘了点赞关注哦。
|