关于跨域问题,你需要知道什么

跨域问题的来源是浏览器为了请求安全而引入的基于同源策略 的安全特性,当页面和请求的协议、主机名或端口不一致时,浏览器判定两者不同源,即为跨域请求。

注意事项:

  • 跨域请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截
  • 表单的方式可以发起跨域请求是因为表单并不会获取新的内容
  • 有三个标签是允许跨域加载资源:img、link、script
  • 跨域是浏览器的限制,服务端并不受此影响

1 CORS (Cross-Origin Resource Sharing)

CORS 是目前最为广泛的解决跨域问题的方案。方案依赖服务端/后端在响应头中添加Access-Control-Allow-*头,告知浏览器端通过此请求。

涉及到的端

CORS 只需要服务端/后端支持即可,不涉及前端改动。

具体实现方式

CORS 将请求分为简单请求(Simple Requests)需预检请求(Preflighted requests) ,不同场景有不同的行为。

简单请求

不会触发预检请求的称为简单请求。当请求同时满足以下条件时就是一个简单请求:

  • 请求方法:GET、HEAD、POST。
  • 请求头:Accept、Accept-Language、Content-Language、Content-Type。
  • Content-Type 仅支持:application/x-www-form-urlencoded、multipart/form-data、text/plain。

需预检请求

当一个请求不满足以上简单请求的条件时,浏览器会自动向服务端发送一个 OPTIONS 请求

js 复制代码
OPTIONS /resource HTTP/1.1
Host: example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type, Authorization

通过服务端返回的 Access-Control-Allow-* 判定请求是否被允许

js 复制代码
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization

CORS 引入了以下几个以Access-Control-Allow-*开头:

  • Access-Control-Allow-Origin 表示允许的来源
  • Access-Control-Allow-Methods 表示允许的请求方法
  • Access-Control-Allow-Headers 表示允许的请求头
  • Access-Control-Allow-Credentials 表示允许携带认证信息

当请求符合响应头的这些条件时,浏览器才会发送并响应正式的请求。

2 反向代理

反向代理解决跨域问题的方案依赖同源的服务端对请求做一个转发处理,将请求从跨域请求转换成同源请求。

涉及到的端

反向代理只需要服务端/后端支持,几乎不涉及前端改动,只用切换接口即可。

具体实现方式

反向代理的实现方式为在页面同域下配置一套反向代理服务,页面请求同域的服务端,服务端请求上游的实际的服务端,之后将结果返回给前端。

3 JSONP

JSONP 是一个相对古老的跨域解决方案。利用 script 标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据

  • 需要对方的服务器做支持
  • 优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题。
  • 缺点是仅支持get方法具有局限性、不安全可能会遭受XSS攻击
  • JSONP都是GET和异步请求的,且jQuery默认就会给JSONP的请求清除缓存

具体实现方式

  • 声明一个回调函数,其函数名(如show)当做参数值,要传递给跨域请求数据的服务器,函数形参为要获取目标数据(服务器返回的data)。
  • 创建一个script标签,把那个跨域的API数据接口地址,赋值给script的src,还要在这个地址中向服务器传递该函数名(可以通过问号传参:?callback=show)。
  • 服务器接收到请求后,需要进行特殊的处理:把传递进来的函数名和它需要给你的数据拼接成一个字符串,例如:传递进去的函数名是show,它准备好的数据是show('我不爱你')。
  • 最后服务器把准备的数据通过HTTP协议返回给客户端,客户端再调用执行之前声明的回调函数(show),对返回的数据进行操作。

非常用方式

postMessage

  • 即在两个 origin 下分别部署一套页面 A 与 B,A 页面通过 iframe 加载 B 页面并监听消息,B 页面发送消息。

window.name

  • 主要是利用 window.name 页面跳转不改变的特性实现跨域,即 iframe 加载一个跨域页面,设置 window.name,跳转到同域页面,可以通过 $('iframe').contentWindow.name 拿到跨域页面的数据。

document.domain

  • 可将相同一级域名下的子域名页面的 document.domain 设置为一级域名实现跨域。
  • 可将同域不同端口的 document.domain 设置为同域名实现跨域(端口被置为 null)。

websocket

Websocket是HTML5的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。WebSocket和HTTP都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。同时,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。

原生WebSocket API使用起来不太方便,可以使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。

总结

  • CORS支持所有类型的HTTP请求,可以更细粒度地控制哪些域可以访问资源

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

  • 不管是Node中间件代理还是nginx反向代理,主要是通过同源策略对服务器不加限制。

  • 日常工作中,用得比较多的跨域方案是cors和nginx反向代理

Ref:juejin.cn/post/684490...

相关推荐
m0_748256787 分钟前
SpringBoot 依赖之Spring Web
前端·spring boot·spring
web1350858863535 分钟前
前端node.js
前端·node.js·vim
m0_5127446436 分钟前
极客大挑战2024-web-wp(详细)
android·前端
若川1 小时前
Taro 源码揭秘:10. Taro 到底是怎样转换成小程序文件的?
前端·javascript·react.js
潜意识起点1 小时前
精通 CSS 阴影效果:从基础到高级应用
前端·css
奋斗吧程序媛1 小时前
删除VSCode上 origin/分支名,但GitLab上实际上不存在的分支
前端·vscode
IT女孩儿1 小时前
JavaScript--WebAPI查缺补漏(二)
开发语言·前端·javascript·html·ecmascript
m0_748256563 小时前
如何解决前端发送数据到后端为空的问题
前端
请叫我飞哥@4 小时前
HTML5适配手机
前端·html·html5
@解忧杂货铺5 小时前
前端vue如何实现数字框中通过鼠标滚轮上下滚动增减数字
前端·javascript·vue.js