跨域是如何形成的?

当我们请求一个url的 协议、域名、端口三者之间任意一个与当前页面url的协议、域名、端口 不同这种现象我们把它称之为跨域

跨域会导致:
1、无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
2、无法接触非同源网页的 DOM
3、无法向非同源地址发送 AJAX 请求(可以发送,但浏览器会拒绝接受响应)

导致跨域的根本原因是请求浏览器的同源策略导致的 ,而跨域请求报错的原因是: 浏览器同源策略 && 请求是ajax类型 && 请求确实跨域了。

解决方法: jsonp,cors,代理转发

1.jsonp

jsonp 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求
原理:在浏览器上 <script>、<img>、<link>、<iframe>等标签都可以加载跨域资源 且不受同源限制,可以用来作为请求,后端接受请求后返回一个回调函数callback,调用前端已经定义好的函数,从而实现跨域请求.

举个很简单的例子 : 我们通过img标签的src属性, 请求一个网络地址的图片 ,这就是非同源请求了 ,但是由于浏览器的同源策略只对ajax请求有效所以 我们的请求不会受到影响 。换句话来说 只有ajax请求才会产生跨域问题。

举个例子:动态创建 script 标签,利用 script 标签的 src 请求没有跨域的限制.

function updateList (data) {
    console.log(data);
}
let tag = document.createElement("script")
tag.src = "http://otherdomain.com/request?callback=updateList";
document.head.appendChild(tag);

代码定义一个全局函数,然后把这个函数名添加到 script 标签中 src 属性的参数 callback 中,
script 的 src 就是需要跨域的请求.服务端收到请求之后,将数据放入 callback 属性的属性值中:
updateList("somedata"),然后返回给客户端:

// script 响应返回的js内容为
updateList([{
    name: 'hello'
}]);

也就是客户端执行 传递的方法 updateList ,函数的参数即是本次跨域请求返回的数据。

2.CORS

服务器设置:

ACCESS-CONTROL-ALLOW-ORIGIN: *

只要浏览器检测到响应头带上了 CORS,并且允许的源包括了本网站,那么就不会拦截请求响应。

CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。

CORS允许任何类型的请求。在使用CORS来访问数据的时候,客户端不需要更改任何数据访问逻辑。所有的一切工作都是在服务端及浏览器之间自动完成的。前端代码与发送普通Ajax请求没有差异,我们只需在服务端设置即可(后端的活).

3.代理转发

在前端服务和后端接口服务之间 架设一个中间代理服务,它的地址保持和前端服务器一致服务器与服务器之间的数据请求是没有跨域这个问题的。那么:
这样,我们就可以通过中间这台服务器做接口转发,在开发环境下解决跨域问题,看起来好像挺复杂,其实vue-cli已经为我们内置了该技术,我们只需要按照要求配置一下即可。

vue.config.js 的devServer(开发环境)里 配置代理服务器 通过这个代理服务器发送请求 这样就不纯在跨域的问题了 代码如下:

module.exports = {
  devServer:{
    proxy:{
        // 如果请求地址以/api打头,就出触发代理机制
       "/api":{
             target:"https://****.com" //数据接口的地址  我们要代理的真实接口地址
             changeOrigin:true,  // 允许跨域 
             secure:false, // 允许运行在https上   
             pathRewrite: { //如果你不想总是传递 /api,可以重写路径
                  '^/api': ''
             }   
        }
         
    }
}

把target改成你的接口地址前面的那部分就好了,底下的^/api就是把前面那些替代成空字符串,接口就写替代的后面那部分路由地址就好了,不过我推荐不要用‘/api’还是用‘’空字符串代替,毕竟你前端代理在路由前面加了/api。在本地浏览器前面会替代的那部分会显示为localhost,其原理就是解决跨域问题中的设置代理。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐