跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制。
同源策略:是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。所谓的同源,指的是协议、域名、端口相同。浏览器处于安全方面的考虑,只允许本域名下的接口交互,不同源的客户端脚本,在没有明确授权的情况下,不能读写对方的资源。
- Cookie , LocalStorage ,IndexedDB等存储性内容。
- DOM节点
- AJAX请求发送后,非同源会被浏览器拦截。
但是有三个标签是允许跨域加载资源:
反向代理:隐藏真实的服务器端
正向代理:隐藏真实的客户端
介绍
Nginx 通过反向代理的方式保证当前域,能获取到静态资源和接口,不关心是怎么获取的。
Nginx 从入门到实践
nginx反向代理和负载均衡策略实战案例
配置 Nginx
实现
前端代码
后端代码
CORS(cross-origin resource sharing),跨源资源共享(一般俗称『跨域请求』),跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的 Web 应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器「不同的域、协议或端口」请求一个资源时,资源会发起一个「跨域 HTTP 请求。
MDN 上的介绍 (developer.mozilla.org/en-US/docs/…
而在 cors 中会有 简单请求 和 预检请求(preflighted requests)的概念。
浏览器支持情况:当你使用 IE<=9, Opera<12, or Firefox<3.5 或者更加老的浏览器,这个时候请使用 JSONP 。
简单请求
不会触发 CORS 预检请求。这样的请求为“简单请求”,请注意,该术语并不属于 Fetch (其中定义了 CORS)规范。
若请求满足所有下述条件,则该请求可视为“简单请求”:
- HTTP 方法只能是 GET、HEAD 或 POST;
- HTTP 头只能是 Accept/Accept-Language/Conent-Language/Content-Type/DPR/Downlink/Save-Data/Viewport-Width/Width;
- Content-Type 头只能是 text/plain、multipart/form-data 或 application/x-www-form-urlencoded。
- 请求中的任意 对象均没有注册任何事件监听器; 对象可以使用 属性访问。
- 请求中没有使用 对象。
非简单请求
除以上情况外的。
看上去很是复杂。那么怎么理解这些限制呢?
其实,简单请求就是普通 HTML Form 在不依赖脚本的情况下可以发出的请求,比如表单的 method 如果指定为 POST ,可以用 enctype 属性指定用什么方式对表单内容进行编码,合法的值就是前述这三种。
非简单请求就是普通 HTML Form 无法实现的请求。比如 PUT 方法、需要其他的内容编码方式、自定义头之类的。
对于服务器来说,第一,许多服务器压根没打算给跨源用。当然你不给 CORS 响应头,浏览器也不会使用响应结果,但是请求本身可能已经造成了后果。所以最好是默认禁止跨源请求。
第二,要回答某个请求是否接受跨源,可能涉及额外的计算逻辑。这个逻辑可能很简单,比如一律放行。也可能比较复杂,结果可能取决于哪个资源哪种操作来自哪个 origin。对浏览器来说,就是某个资源是否允许跨源这么简单;对服务器来说,计算成本却可大可小。所以我们希望最好不用每次请求都让服务器劳神计算。
CORS-preflight 就是这样一种机制,浏览器先单独请求一次,询问服务器某个资源是否可以跨源,如果不允许的话就不发实际的请求。注意先许可再请求等于默认禁止了跨源请求。如果允许的话,浏览器会记住,然后发实际请求,且之后每次就都直接请求而不用再询问服务器否可以跨源了。于是,服务器想支持跨源,就只要针对 preflight 进行跨源许可计算。本身真正的响应代码则完全不管这个事情。并且因为 preflight 是许可式的,也就是说如果服务器不打算接受跨源,什么事情都不用做。
但是这机制只能限于非简单请求。在处理简单请求的时候,如果服务器不打算接受跨源请求,不能依赖 CORS-preflight 机制。因为不通过 CORS,普通表单也能发起简单请求,所以默认禁止跨源是做不到的。
既然如此,简单请求发 preflight 就没有意义了,就算发了服务器也省不了后续每次的计算,反而在一开始多了一次 preflight。
有些人把简单请求不需要 preflight 理解为『向下兼容』。这也不能说错。但严格来说,并不是『为了向下兼容』而不能发。理论上浏览器可以区别对待表单请求和非表单请求 —— 对传统的跨源表单提交不发 preflight,从而保持兼容,只对非表单跨源请求发 preflight。
但这样做并没有什么好处,反而把事情搞复杂了。比如本来你可以直接用脚本发跨源普通请求,尽管(在服务器默认没有跨源处理的情况下)你无法得到响应结果,但是你的需求可能只是发送无需返回,比如打个日志。但现在如果服务器不理解 preflight 你就干不了这个事情了。
而且如果真的这样做,服务器就变成了默认允许跨源表单,如果想控制跨源,还是得(跟原本一样)直接在响应处理中执行跨源计算逻辑;另一方面服务器又需要增加对 preflight 请求的响应支持,执行类似的跨源计算逻辑以控制来自非表单的相同跨源请求。服务器通常没有区分表单/非表单差异的需求,这样搞纯粹是折腾服务器端工程师。
所以简单请求不发 preflight 不是因为不能兼容,而是因为兼容的前提下发 preflight 对绝大多数服务器应用来说没有意义,反而把问题搞复杂了。
Node 中的解决方案
原生方式
我们来看下后端部分的解决方案。 中 的解决代码.
第三方中间件
为了方便也可以直接使用中间件
关于 cors 的 cookie 问题
想要传递 需要满足 3 个条件
1.web 请求设置
这里默认情况下在跨域请求,浏览器是不带 cookie 的。但是我们可以通过设置 来进行传递 .
2. 为
3.为非
这里请求的方式,在 中是能看到返回值的,但是只要不满足以上其一,浏览器会报错,获取不到返回值。
前端示例
分别演示一下前端部分 和
简单请求
非简单请求
这里我们加入了一个非集合内的 头 来达到非简单请求的目的。
小结
代理的思路为,利用服务端请求不会跨域的特性,让接口和当前站点同域。
代理前
这样,所有的资源以及请求都在一个域名下了。
cli 工具中的代理
1) Webpack (4.x)
在中可以配置来快速获得接口代理的能力。
使用自己的代理工具
cors-anywhere
服务端:
前端代码:
效果展示:
charles
介绍
这是一个测试、开发的神器。介绍与使用
利用 charles 进行跨域,本质就是请求的拦截与代理。
在 中设置代理
前端代码
后端代码
效果
访问 http://localhost:8000/charles
主要就是利用了 标签没有跨域限制的这个特性来完成的。
使用限制
仅支持 GET 方法,如果想使用完整的 REST 接口,请使用 CORS 或者其他代理方式。
流程解析
1.前端定义解析函数(例如 jsonpCallback=function(){....})
2.通过 params 形式包装请求参数,并且声明执行函数(例如 cb=jsonpCallback)
3.后端获取前端声明的执行函数(jsonpCallback),并以带上参数并调用执行函数的方式传递给前端。
使用示例
后端实现
普通 js 示例
JQuery Ajax 示例
原理解析
我们稍稍改造一下,外链的形式。
我们再改造一下,我们把这个外链的 js 就当做是一个动态的接口,因为本身资源和接口一样,是一个请求,也包含各种参数,也可以动态化返回。
你仔细品,细细品,是不是 jsonp 有的优势就是 script 加载 js 的优势,加载的方式只不过换了一种说法。这也告诉我们一个道理,很多东西并没有那么神奇,是在你所学的知识范围内。就好比,桃树和柳树,如果你把他们当成很大跨度的东西去记忆理解,那么世上这么多树,你真的要累死了,你把他们都当成是树,哦吼?你会突然发现,你对世界上所有的树都有所了解,他们都会长叶子,光合作用....当然也有个例,但是你只需要去记忆这些细微的差别,抓住主干。。。嗯,反正就这么个道理。
WebSocket 规范定义了一种 API,可在网络浏览器和服务器之间建立“套接字”连接。简单地说:客户端和服务器之间存在持久的连接,而且双方都可以随时开始发送数据。详细教程可以看 www.html5rocks.com/zh/tutorial…
这种方式本质没有使用了 HTTP 的响应头, 因此也没有跨域的限制,没有什么过多的解释直接上代码吧。
前端部分
后端部分
window.postMessage() 方法可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为 https),端口号(443 为 https 的默认值),以及主机 (两个页面的模数 设置为相同的值) 时,这两个脚本才能相互通信。window.postMessage() 方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。
用途
1.页面和其打开的新窗口的数据传递
2.多窗口之间消息传递
3.页面与嵌套的 iframe 消息传递
用法
- 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 是
b.html 为中间代理页,与 a.html 同域,内容为空。
通过 iframe 的 src 属性由外域转向本地域,跨域数据即由 iframe 的 window.name 从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。
非特殊必要情况,不建议使用。
Windows
Mac
这个目录可以自定义.
CORS 为什么要区分『简单请求』和『预检请求』?
到此这篇跨域是什么错误码(跨域请求是什么)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/bcyy/74561.html