当前位置:网站首页 > 前端开发 > 正文

前端跨域解决方案(前端跨域解决方案cors设置星号)



这是一个老生常谈的话题,以前我觉得这种基础文章没有什么好写的,最近为了线上问题深入了解底层,确实有点东西,下面汇总成10种方案。

重要的说明: 在文中,web 端地址为 localhost:8000 服务端地址为 localhost:8080,这一点希望你能记住,会贯穿全文,你也可以把此处的两端的地址代入你自己的地址。

以下所有代码均在https://github.com/hua/node-demo/tree/master/node-cors

跨域问题其实就是浏览器的同源策略所导致的。

同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。

--来源 MDN

当跨域时会收到以下错误

那么如何才算是同源呢?先来看看 url 的组成部分

只有当

protocol(协议)、domain(域名)、port(端口)三者一致。

protocol(协议)、domain(域名)、port(端口)三者一致。

protocol(协议)、domain(域名)、port(端口)三者一致。

才是同源。

以下协议、域名、端口一致。

http://www.example.com:80/a.js

http://www.example.com:80/b.js

以下这种看上去再相似也没有用,都不是同源。

http://www.example.com:8080

http://www2.example.com:80

在这里注意一下啊,这里是为了突出端口的区别才写上端口。在默认情况下 http 可以省略端口 80, https 省略 443。这别到时候闹笑话了,你和我说http://www.example.com:80和http://www.example.com不是同源,他俩是一个东西。

http://www.example.com:80===http://www.example.com

https://www.example.com:443===https://www.example.com

唔,还是要说明一下。

跨域资源共享(CORS) 是一种机制,它使用额外的HTTP头来告诉浏览器 让运行在一个 origin (domain) 上的 Web 应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求

而在 cors 中会有和的概念。

浏览器支持情况

当你使用 IE<=9, Opera<12, or Firefox<3.5 或者更加老的浏览器,这个时候请使用 JSONP 。

a.简单请求

不会触发CORS 预检请求。这样的请求为“简单请求”,请注意,该术语并不属于Fetch(其中定义了 CORS)规范。若请求满足所有下述条件,则该请求可视为“简单请求”:

情况一: 使用以下方法(意思就是以下请求意外的都是非简单请求)

情况二: 人为设置以下集合外的请求头

  • (需要注意额外的限制)

情况三:的值仅限于下列三者之一:(例如 application/json 为非简单请求)

情况四:

请求中的任意对象均没有注册任何事件监听器;对象可以使用属性访问。

情况五:

请求中没有使用对象。

b.非简单请求

除以上情况外的。

c.Node 中的解决方案

原生方式

我们来看下后端部分的解决方案。中的解决代码.

第三方中间件

为了方便也可以直接使用中间件

golang中使用:
关于 cors 的 cookie 问题

想要传递需要满足 3 个条件

1.web请求设置

这里默认情况下在跨域请求,浏览器是不带 cookie 的。但是我们可以通过设置来进行传递.

2.为

3.为非

这里请求的方式,在中是能看到返回值的,但是只要不满足以上其一,浏览器会报错,获取不到返回值。

d.前端示例

分别演示一下前端部分和

简单请求
非简单请求

这里我们加入了一个非集合内的头来达到非简单请求的目的。

非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的请求,否则就报错。

"预检"请求用的请求方法是,表示这个请求是用来询问的。头信息里面,关键字段是,表示请求来自哪个源。

除了字段,"预检"请求的头信息包括两个特殊字段。

(1)Access-Control-Request-Method

该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是。

(2)Access-Control-Request-Headers

该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,上例是。

服务器收到"预检"请求以后,检查了、和字段以后,确认允许跨源请求,就可以做出回应。

上面的HTTP回应中,关键的是字段,表示可以请求数据。该字段也可以设为星号,表示同意任意跨源请求。

如果服务器否定了"预检"请求,会返回一个正常的HTTP回应,但是没有任何CORS相关的头信息字段。这时,浏览器就会认定,服务器不同意预检请求,因此触发一个错误,被对象的回调函数捕获。控制台会打印出如下的报错信息。

服务器回应的其他CORS相关字段如下。

小结

1、 在新版的 chrome 中,如果你发送了复杂请求,你却看不到请求。可以在这里设置设置成,或者升级到最新版本chrome,重启浏览器。对于非简单请求就能看到请求了。

2、 一般情况下后端接口是不会开启这个跨域头的,除非是一些与用户无关的不太重要的接口。

一旦服务器通过了"预检"请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样,会有一个头信息字段。服务器的回应,也都会有一个头信息字段。

下面是"预检"请求之后,浏览器的正常CORS请求。

上面头信息的字段是浏览器自动添加的。

下面是服务器正常的回应。

上面头信息中,字段是每次回应都必定包含的。

代理的思路为,利用服务端请求不会跨域的特性,让接口和当前站点同域。

这样,所有的资源以及请求都在一个域名下了。

a.cli 工具中的代理

1) Webpack (4.x)

在中可以配置来快速获得接口代理的能力。

修改前端接口请求方式,改为不带域名。(因为现在是同域请求了)

2) Vue-cli 2.x
3) Vue-cli 3.x
4) Parcel (2.x)

看到这里,心里一句 xxx 就会脱口而出,一会写配置文件,一会 proxyTable ,一会 proxy,怎么这么多的形式?学不动了学不动了。。。不过也不用慌,还是有方法的。以上所有配置都是有着共同的底层包http-proxy-middleware.里面需要用到的各种,等功能,直接看这个库的配置就可以了。关于 http-proxy-middleware 这个库的原理可以看我这篇文章https://github.com/hua/proxy当然了。。。对于配置的位置入口还是非统一的。教一个搜索的技巧吧,上面配置写哪里都不用记的,想要哪个框架的 直接 google 搜索 xxx proxy 就行了。

例如 vue-cli 2 proxy 、 webpack proxy 等等....基本会搜到有官网的配置答案,通用且 nice。

b.使用自己的代理工具

cors-anywhere

服务端

前端代码

效果展示

缺点

无法专递 cookie,原因是因为这个是一个代理库,作者觉得中间传递 cookie 太不安全了。https://github.com/Rob--W/cors-anywhere/issues/208#issuecomment-

c.charles

介绍

这是一个测试、开发的神器。介绍与使用

利用 charles 进行跨域,本质就是请求的拦截与代理。

在中设置代理

前端代码
后端代码
效果

访问http://localhost:8000/charles

完美解决。

唔。这里又有一个注意点。在中会出现抓不到本地包的情况。这个时候需要自定义一个域名,然后配置指定到。然后修改访问方式。

介绍

Nginx 则是通过反向代理的方式,(这里也需要自定义一个域名)这里就是保证我当前域,能获取到静态资源和接口,不关心是怎么获取的。nginx 安装教程

配置下 hosts

配置 nginx

启动 nginx

重启 nginx

实现

前端代码

后端代码

效果

访问

主要就是利用了标签没有跨域限制的这个特性来完成的。

使用限制

仅支持 GET 方法,如果想使用完整的 REST 接口,请使用 CORS 或者其他代理方式。

流程解析

1.前端定义解析函数(例如 jsonpCallback=function(){....})

2.通过 params 形式包装请求参数,并且声明执行函数(例如 cb=jsonpCallback)

3.后端获取前端声明的执行函数(jsonpCallback),并以带上参数并调用执行函数的方式传递给前端。

使用示例

后端实现

普通 js 示例

JQuery Ajax 示例

原理解析

其实这就是 js 的魔法

我们先来看最简单的 js 调用。嗯,很自然的调用。

我们稍稍改造一下,外链的形式。

我们再改造一下,我们把这个外链的 js 就当做是一个动态的接口,因为本身资源和接口一样,是一个请求,也包含各种参数,也可以动态化返回。

你仔细品,细细品,是不是 jsonp 有的优势就是 script 加载 js 的优势,加载的方式只不过换了一种说法。这也告诉我们一个道理,很多东西并没有那么神奇,是在你所学的知识范围内。就好比,桃树和柳树,如果你把他们当成很大跨度的东西去记忆理解,那么世上这么多树,你真的要累死了,你把他们都当成是树,哦吼?你会突然发现,你对世界上所有的树都有所了解,他们都会长叶子,光合作用....当然也有个例,但是你只需要去记忆这些细微的差别,抓住主干。。。嗯,反正就这么个道理。

WebSocket规范定义了一种 API,可在网络浏览器和服务器之间建立“套接字”连接。简单地说:客户端和服务器之间存在持久的连接,而且双方都可以随时开始发送数据。详细教程可以看https://www.html5rocks.com/zh/tutorials/websockets/basics/

这种方式本质没有使用了 HTTP 的响应头, 因此也没有跨域的限制,没有什么过多的解释直接上代码吧。

前端部分

后端部分

window.postMessage()方法可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为 https),端口号(443 为 https 的默认值),以及主机 (两个页面的模数设置为相同的值) 时,这两个脚本才能相互通信。window.postMessage()方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。

用途

1.页面和其打开的新窗口的数据传递

2.多窗口之间消息传递

3.页面与嵌套的 iframe 消息传递

用法

详细用法看https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage

  • otherWindow: 其他窗口的一个引用,比如 iframe 的 contentWindow 属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。
  • message: 将要发送到其他 window 的数据。
  • targetOrigin: 通过窗口的 origin 属性来指定哪些窗口能接收到消息事件.
  • transfer(可选) : 是一串和 message 同时传递的对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权

示例

index.html

another.html

从第 7 种到第 9 种方式,我觉得别人的写的已经很好了,为了完整性,我就拿别人的了。如有雷同....(不对,就是雷同....)不要说不出来。

该方式只能用于二级域名相同的情况下,比如和适用于该方式。 只需要给页面添加表示二级域名都相同就可以实现跨域。

实现原理

原理就是通过 url 带 hash ,通过一个非跨域的中间页面来传递数据。

实现流程

一开始 a.html 给 c.html 传一个 hash 值,然后 c.html 收到 hash 值后,再把 hash 值传递给 b.html,最后 b.html 将结果放到 a.html 的 hash 值中。 同样的,a.html 和 b.htm l 是同域的,都是,而 c.html 是

window 对象的 name 属性是一个很特别的属性,当该 window 的 location 变化,然后重新加载,它的 name 属性可以依然保持不变。

其中 a.html 和 b.html 是同域的,都是,而 c.html 是

b.html 为中间代理页,与 a.html 同域,内容为空。

通过 iframe 的 src 属性由外域转向本地域,跨域数据即由 iframe 的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。

其实讲下其实跨域问题是浏览器策略,源头是他,那么能否能关闭这个功能呢?

答案是肯定的。

注意事项: 因为浏览器是众多 web 页面入口。我们是否也可以像客户端那种,就是用一个单独的专门宿主浏览器,来打开调试我们的开发页面。例如这里以 chrome canary 为例,这个是我专门调试页面的浏览器,不会用它来访问其他 web url。因此它也相对于安全一些。当然这个方式,只限于当你真的被跨域折磨地崩溃的时候才建议使用以下。使用后,请以正常的方式将他打开,以免你不小心用这个模式干了其他的事。

Windows

Mac

这个目录可以自定义.

效果展示

嗯,使用起来很香,但是再次提醒,一般情况千万别轻易使用这个方式,这个方式好比七伤拳,使用的好威力无比,使用不好,很容易伤到自己。

在最一开始,我们知道了,跨域只存在于浏览器端。而浏览器为 web 提供访问入口。我们在可以浏览器内打开很多页面。正是这样的开放形态,所以我们需要对他有所限制。就比如林子大了,什么鸟都有,我们需要有一个统一的规范来进行约定才能保障这个安全性。

这里还是用最常用的方式来讲解,例如用户登录 a 网站,同时新开 tab 打开了 b 网站,如果不限制同源, b 可以像 a 网站发起任何请求,会让不法分子有机可趁。

如果可以进行 dom 操作...那么大家的信息在这种钓鱼网站眼里都是一颗颗小白菜,等着被收割。

可以在 http 返回头 添加防止被别人添加至 iframe。

CORS与JSONP的使用目的相同,但是比JSONP更强大。

JSONP只支持请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。

以上最常用、最重要的是CORS、代理、JSONP,我里面也提到了多种示例,大家可以慢慢消化一下。希望未来有更加安全的方式来限制 web ,解决跨域的头疼,哈哈。

参考:

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS

https://www.ruanyifeng.com/blog/2016/04/cors.html

到此这篇前端跨域解决方案(前端跨域解决方案cors设置星号)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • 前端工程化体系(前端工程化概念)2024-12-21 10:54:07
  • 前端埋点工具(前端埋点插件)2024-12-21 10:54:07
  • 前端工程化的理解面试题(什么是前端工程化.前端面试题)2024-12-21 10:54:07
  • webflux前景(webflux 前端)2024-12-21 10:54:07
  • 前端富文本框(前端富文本框 从word复制的)2024-12-21 10:54:07
  • 前端工程化面试题(前端面试题目及答案2019)2024-12-21 10:54:07
  • 前端富文本框(前端富文本框上传图片)2024-12-21 10:54:07
  • 前端工程师面经(前端工程师的面试题)2024-12-21 10:54:07
  • 前端工程化(前端工程化包括哪些方面)2024-12-21 10:54:07
  • 前端跨域请求(前端跨域请求头)2024-12-21 10:54:07
  • 全屏图片