记一次CORS踩坑记录

前言

之前某一次远程工作的内容是配置并且实现CORS的跨域访问,本来特别简单的问题,却因为Spring的封装“坑”的有点惨,而且涉及一个IE浏览器跨域失败的问题处理比较麻烦,下面为整个cors跨域问的解决记录和笔记。

什么是ajax跨域?

简单来说就是如果使用ajax访问不同端口的IP等非同源的资源,就会出现跨域,比如下面的网址就会产生跨域的问题。

  • ​http://www.example.com/dir2/other.html​​:同源
  • ​http://example.com/dir/other.html​​:不同源(域名不同)
  • ​http://v2.www.example.com/dir/other.html​​:不同源(域名不同)
  • ​http://www.example.com:81/dir/other.html​​:不同源(端口不同)

下面是跨域的相关报错信息,如果产生跨域我们将无法访问相关的服务器资源,并且通常会给予一定的提示信息:

XMLHttpRequest cannot load . No 'Access-Control-Allow-Origin' header is present on the requested resource.Origin 'http://www.xyz.com' is therefore not allowed access.

如果一个资源跨域,那么浏览器是无法获取下面这些信息的:

(1) Cookie、LocalStorage 和 IndexDB 无法读取。

(2) DOM 无法获得。

(3) AJAX 请求不能发送

跨域算是浏览器常见的一个稍微让人头疼的问题,在html5之前几乎只能通过jsonp的方式解决,不过html5出现之后,为ajax跨域解决了不少的问题。


常见的解决方式

常见的解决方式如下:

  • Jsonp:使用的是Js回调函数的方式,配置比如​​http://xxxx.com?call=func()​​​,这时候可以使用​​<script></script>​​​标签行包裹,并且设置​​src​​​标签,最后发送给服务端处理完成之后进行回调函数的解析即可,这里也有一种方式是使用js的​​eval()​​函数调用脚本代码,当然jsonp的处理方式只能支持get调用,局限性过大。
  • Cross-Origin Resource Sharing 跨域资源共享, CORS是一种允许当前域(domain)的资源(比如html/js/web service)被其他域(domain)的脚本请求访问的机制。

由于html5新增了cors的支持,并且现在几乎没有那个网页不是html5,最终我们使用cors的方案即可,jsonp的方式基本可以忘记。

踩坑原因

由于每个人的项目环境不一,这里仅个个人环境配置遇到的问题。

  1. 如果存在​​web.xml​​​ 配置,访问的时候会忽略掉其他的任何形式的配置,只生效​​xml​​配置
  2. 项目中配置允许post跨域无效并且只能get跨域访问,原因未知,或许为堡垒机的拦截?

解决过程

  1. 在请求当中加入​​@crossxxx​​注解,发现无效
  2. 将请求改为具体的​​RequestMethod.GET​​​ 或者​​POST​​发现情况依旧
  3. 最后使用了spring cors的解决方式,但是发现也不是加个注解就万事大吉了

参考博客

网上的博客有许多的参考解决方案

segmentfault.com/a/119000001… segament一个博客,写得非常棒【推荐

其他资料:

​ www.imooc.com/qadetail/30…​ www.jianshu.com/p/f3840c8c0… 简书介绍CORS

解决办法

解决办法就是使用了Spring的方式配置

更改之后的配置

  1. 使用​​pom.xml​​加入新的依赖,使用Cors的原生支持

JAVA后台配置只需要遵循如下步骤即可:

  • 第一步:获取依赖jar包
    下载 cors-filter-1.7.jar, java-property-utils-1.9.jar 这两个库文件放到lib目录下。(放到对应项目的webcontent/WEB-INF/lib/下)
  • 第二步:如果项目用了Maven构建的,请添加如下依赖到pom.xml中:(非maven请忽视)
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>[ version ]</version>
</dependency>

其中版本应该是最新的稳定版本,CORS过滤器

  1. 在​​web.xml​​当中增加如下配置
  2. 配置的更详细介绍在上面提到的博客当中,这里不多赘述

下面是和​​web.xml​​的有关配置信息。

<!-- 跨域配置:参考 http://www.thomasyoung.cn/fontend/2017/04/01/ajax-session/-->
<filter>
<!-- 原生Cors过滤器配置 -->
<filter-name>CorsFilter</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>

<!--
非跨域请求是否可以通过此过滤器,默认为true;如果设置为false,则只有跨域的请求被允许
-->
<init-param>
<param-name>cors.allowGenericHttpRequests</param-name>
<param-value>true</param-value>
</init-param>

<init-param>
<param-name>cors.allowOrigin</param-name>
<param-value>http://192.168.92.190:8080,http://192.168.92.145:8080,</param-value>
</init-param>
<!--
是否允许来自allowOrigin的子域名的请求,默认不允许;子域名的概念大家应该清楚,www.example.com是example.com的子域名
-->
<init-param>
<param-name>cors.allowSubdomains</param-name>
<param-value>false</param-value>
</init-param>
<!-- cors.allowed.methods -->
<init-param>
<param-name>cors.supportedMethods</param-name>
<param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
</init-param>
<!-- cors.allowed.headers -->
<init-param>
<param-name>cors.supportedHeaders</param-name>
<param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
</init-param>

<init-param>
<param-name>cors.exposedHeaders</param-name>
<!--这里可以添加一些自己的暴露Headers -->
<param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
</init-param>
<!-- 对应 cors.support.credentials -->
<init-param>
<param-name>cors.supportsCredentials</param-name>
<param-value>true</param-value>
</init-param>
<!-- cors.preflight.maxage 最大缓存时间 -->
<init-param>
<param-name>cors.maxAge</param-name>
<param-value>10</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

IE8/IE9 解决拒绝访问的问题

由于遇到此问题的时候要求希望可以兼容IE,所以通过查阅各种网络资料发现了下面的一些参考。

第一种:引入js文件

通过引入下面的js之后让ie可以支持某些jquery调用的缺失的底层方法(真尼玛坑)。

<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.3/jquery.xdomainrequest.min.js" type="text/javascript" charset="utf-8"></script>

第二种:Jquery开启跨域模式

如果使用jquery在发送请求之前可能需要使用下面设置来允许跨域,当然不一定总是需要。

jQuery.support.cors = true

总结

更多是工作遇到问题的临时笔记处理,cors基本查查资料就能很快掌握,html5之后出现cors解决了不少的问题。