什么是跨域?
为什么会出现跨域问题?
遇见跨域,如何解决?
什么是跨域?
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域.
跨域并不是请求发不出,能够正常发送请求,并且服务器收到请求后正常返回结果,但被浏览器拦截了.
为什么会出现跨域问题?
服务器的同源策略,同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,是为了保护本地数据不被JavaScript代码获取回来的数据污染,因此拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但是无法被浏览器接收。
如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
请求url的协议,域名,端口号三个任意一个与当前页面url不同 , 请求是ajax , 请求跨域资源 会引起浏览器跨域报错.
遇见跨域,如何解决?
1.后端写代码(CORS)在响应中添加必要的响应头,响应回来之后,浏览器不报错
(1)CORS原理
CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
(2)CORS优缺点
CORS要求浏览器(>IE10)和服务器的同时支持,是跨域的根本解决方法,由浏览器自动完成。
优点在于功能更加强大支持各种HTTP Method,缺点是兼容性不如JSONP。
(3)用法
a、前端代码(需要判断浏览器是否支持情况)
function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// 此时即支持CORS的情况
// 检查XMLHttpRequest对象是否有“withCredentials”属性
// “withCredentials”仅存在于XMLHTTPRequest2对象里
xhr.open(method, url, true);
} else if (typeof!= "undefined") {
// 否则检查是否支持XDomainRequest,IE8和IE9支持
// XDomainRequest仅存在于IE中,是IE用于支持CORS请求的方式
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// 否则,浏览器不支持CORS
xhr = null;
}
return xhr;
}
var xhr = createCORSRequest('GET', url);
if (!xhr) {
throw new Error('CORS not supported');
}
b、服务器端
response.addHeader(‘Access-Control-Allow-Origin:*’);//允许所有来源访问
response.addHeader(‘Access-Control-Allow-Method:POST,GET’);//允许访问的方式
2.前端用JSONP方式去发请求(jsonp不是ajax请求)
JSONP的流程(以第三方API地址为例,不必考虑后台程序)
声明一个回调函数,其函数名(如fn)当做参数值,要传递给跨域请求数据的服务器,函数形参为要获取目标数据(服务器返回的data)。
创建一个<script>标签,把那个跨域的API数据接口地址,赋值给script的src,还要在这个地址中向服务器传递该函数名(可以通过问号传参:?callback=fn)。
服务器接收到请求后,需要进行特殊的处理:把传递进来的函数名和它需要给你的数据拼接成一个字符串,例如:传递进去的函数名是fn,它准备好的数据是fn([{"name":"jianshu"}])。
最后服务器把准备的数据通过HTTP协议返回给客户端,客户端再调用执行之前声明的回调函数(fn),对返回的数据进行操作。
<script type="text/javascript" src="http://test.com/jsonServerResponse?callback=fn"></script>
//向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字
//处理服务器返回回调函数的数据
<script type="text/javascript">
function fn(data) {
alert(data.msg);
}
</script>
3.代理服务器 (适用于开发阶段)
在vue.config.js
配置文件中,有一项是devServer,加入以下代码
module.exports = {
devServer: {
// ... 省略
// 代理配置
proxy: {
// 如果请求地址以/api打头,就出触发代理机制
// http://localhost:9588/api/login -> http://线上的地址/api/login
'/api': {
target: 'http://线上的地址' // 我们要代理的真实接口地址
}
}
}
}
}
去掉axios基地址
({
timeout: 5000
// baseURL: ''
})
重启项目,验证结果
- 修改了配置文件,一定要重启前端项目
- 再次测试登陆接口,我们发现:跨域问题已经解决了