跨域以及解决跨域的几种方式
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了跨域以及解决跨域的几种方式相关的知识,希望对你有一定的参考价值。
参考技术A跨域是指浏览器允许向服务器发送跨域请求,从而克服Ajax只能 同源 使用的限制。
同源策略 是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议 + 域名 + 端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
常见的跨域场景:
对于简单请求,浏览器会直接发出CORS请求,具体的就是在头信息中,增加一个 Origin 字段。
非简单请求是那种对服务器有特殊要求的请求,譬如 put delete 方法,或者 Content-Type 字段类型是 application/json 的,非简单请求在正式通信前,会增加一次请求,称为预检请求,也就是 options 方法。
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的 XMLHttpRequest 请求,否则就报错。
与简单请求不同的是, option 请求多了2个字段:
Access-Control-Request-Method :必须字段,用来列出浏览器的CORS请求会用到哪些HTTP方法。
Access-Control-Request-Headers :该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段。
服务器收到"预检"请求以后,检查了 Origin 、 Access-Control-Request-Method 和 Access-Control-Request-Headers 字段以后,确认允许跨源请求,就可以做出回应。
表明服务器支持的所有跨域请求的方法。
表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。
表示是否允许发送认证信息(Cookie)。
指定本次预检请求的有效期,单位为秒,允许缓存。在缓存期间,不用发出另一条预检请求。
解决Geoserver请求跨域的几种思路
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/
1.背景描述
跨域问题是浏览器同源安全制引起的特别常见的问题。不同前端语言针对跨域解决方法有所区别。比如Flex语言做跨域请求时,如果中间件存有跨域文件(crossdomain.xml)则可以轻松实现跨域。
而JS开发的前端,针对GET请求则又可以通过JSONP方式解决。补充一下JSONP的原理:通过创建一个 script 标签,将 src 设置为目标请求,插入到 DOM中,服务器接受该请求并返回数据,数据通常被包裹在回调钩子中。根据JSONP的实现原理,我们可以看到其无法支持POST请求方式。
回到我们文章的主题,使用tomcat发布了Geoserver,前端JS脚本通过常规JSONP的请求方式失效,此时如何实现跨域请求呢?
这里我总结两种思路,一种是转发代理方案,另一种是中间件支持跨域共享机制(CORS)。
2.方案一:转发代理
2.1基于Nginx的代理
假设有A服务器和B服务器,用户前端加载了A服务器的JS资源,然后该JS向B服务器后台发送请求,此时发生了跨域。基于Nginx的解决方案则是,在C(或者A或者B或者其他)服务器上搭建一个Nginx服务器,该服务器对A服务和B服务均做统一端口的代理,即前端通过同一IP:Port访问A上和B上的资源,从而避免浏览器的跨域问题。
方案示意图为:
2.2自定义实现代理转发(基于A服务器)
2.2.1原理
目前A服务器上的脚本想访问B服务器上的服务会引发跨域,如果我们将A服务器的脚本访问转移到A服务器上的后台对B服务器后台的访问,则可以规避跨域问题。
方案示意图为:
2.2.2具体实现
如果我们的代码层面仅仅是单独针对某个请求让其转移至后台,则其他类似问题则无法通用此解决方案。这里我们可以设计一种通用型的解决方案:
a.将所有需要走后台避免跨域的请求统一定义为http://IP:Port/name/proxy?Url=BServerUrl。
b.后台对应的proxy方法中获取到Url后的参数,并且再次对Url后的参数进行传递参数的解析(BServerUrl中可以用&包含正常参数)。
c.转发解析到的B请求,获取返回结果再返回至前端。
注意,在实现中,我们还要同时考虑代理转发的Get请求和Post请求方式:
3.方案二:中间件跨域共享机制(CORS)
3.1CORS原理简介
出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求。 例如,XMLHttpRequest和Fetch API遵循同源策略。 这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非使用CORS头文件。
CORS的原理为:跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。
以上内容均摘抄于:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS。
3.2具体实现
先下载CORS对应的Jar:
<!-- cors-filter-->
<dependency org="com.thetransactioncompany" name="java-property-utils" rev="1.10" conf="common-release->default;" />
<dependency org="com.thetransactioncompany" name="cors-filter" rev="2.5" conf="common-release->default;"/>
在Geoserver的Web.xml中加上如下配置:
重启Geoserver后测试。
测试环境说明:在同一台机器上测试,系统采用8081端口,Geoserver服务采用8080端口,不同端口同样会导致跨域。测试结果为跨域成功。
-----欢迎转载,但保留版权,请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/
如果您觉得本文确实帮助了您,可以微信扫一扫,进行小额的打赏和鼓励,谢谢 ^_^
以上是关于跨域以及解决跨域的几种方式的主要内容,如果未能解决你的问题,请参考以下文章