转载:https://blog.csdn.net/lmy86263/article/details/51724221

由于工程合作开发的需要,后台的应用要能支持跨域访问,但是在这个跨域访问“时好时坏”,我们这帮屌丝所知道的就是加上两个jar包,然后声明一下Filter,感觉很简单的有没有!!感觉自己很牛X有没有!!全是幻觉!!要不然怎么会时好时坏!!为了深入了解这个问题,决定写这篇文章总结一下。 
要知道跨域请求就要先了解同源策略,那么什么是同源?什么是不同源?简单来说就是,如果两个资源,包括HTML页面、JavaScript脚本、css样式,对应的协议、域名和端口完全相同,那么这两个资源就是同源的,Same-origin policy解释得很清楚。那么同源策略的意思就是一个源中的资源访问另外一个源中的资源,在在这一点上JavaScript的跨站资源访问表现的更加明显。在HTML5之前Ajax是不允许发起跨站请求的,如果有需求的话,可以使用JSONP等方法,但是缺点就是:

  • 只支持Get不支持Post;
  • 本质上是脚本注入的方式,存在安全隐患;

还有JSONP的优缺点,但是自从HTML5出现之后,提出了CORS(跨站资源共享)这种方式,极大地方便了日常的开发。如果要理解CORS的工作原理,首先要知道跨域访问是怎么被禁止的,之前本屌丝一直以为是前台的跨域访问请求不能发出去,是实现同源策略的浏览器拦截了该请求,但是后来才知道浏览器并没有拦截请求,而是拦截了服务器端返回的响应。 
所以如果要支持跨域访问,需要浏览器和后台服务器程序同时支持,如果这两个条件不能同时满足,则还是不能支持跨域访问。

用于CORS中的Http的首部有如下几个:

  • 响应头

    • Access-Control-Allow-Origin: 允许跨域访问的域,可以是一个域的列表,也可以是通配符”*”;
    • Access-Control-Allow-Methods: 允许使用的请求方法,以逗号隔开;
    • Access-Control-Allow-Headers: 允许自定义的头部,以逗号隔开,大小写不敏感;
    • Access-Control-Expose-Headers: 允许脚本访问的返回头,请求成功后,脚本可以在XMLHttpRequest中访问这些头的信息
    • Access-Control-Allow-Credentials: 是否允许请求带有验证信息,XMLHttpRequest请求的withCredentials标志设置为true时,认证通过,浏览器才将数据给脚本程序。
    • Access-Control-Max-Age: 缓存此次请求的秒数。在这个时间范围内,所有同类型的请求都将不再发送预检请求而是直接使用此次返回的头作为判断依据,非常有用,大幅优化请求次数;
  • 请求头

    • Origin: 普通的HTTP请求也会带有,在CORS中专门作为Origin信息供后端比对,表明来源域,要与响应头中的Access-Control-Allow-Origin相匹配才能进行跨域访问;
    • Access-Control-Request-Method: 将要进行跨域访问的请求方法,要与响应头中的Access-Control-Allow-Methods相匹配才能进行跨域访问;
    • Access-Control-Request-Headers: 自定义的头部,所有用setRequestHeader方法设置的头部都将会以逗号隔开的形式包含在这个头中,要与响应头中的Access-Control-Allow-Headers相匹配才能进行跨域访问

从支持跨域访问的范围说,可以有整个服务器、单个应用程序、单个接口。

1、在整个服务器上支持跨域访问

在服务器上可以部署多个应用程序,如果在整个服务器的范围上支持跨域访问,那么在所有应用程序上都不用单独配置了,直接使用服务器的配置即可,这里通过tomcat来进行举例。在Tomcat7之后包括tomcat7才开始支持CORS,之前的版本是不支持的。配置CORS,首先配置Tomcat中的conf\web.xml,在其中添加一个Filter声明,如下:

<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

这样就能应用到在该Tomcat中部署的所有的应用程序的接口上。然后在Tomcat的lib文件夹下加入两个jar包:cors-filter-2.5.jar和java-property-utils-1.9.jar,这两个jar包对应的maven依赖如下:

<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>2.5</version>
</dependency>

在Tomcat服务器上配置完成后,在自己的应用程序上就不要再配置有关跨域访问的内容了,这样会造成访问相应的接口时不支持跨域访问。 
这种配置方式覆盖面太广,有些部署在该服务器下的应用程序根本不需要支持跨域访问,就会带来一些安全问题,所以其实不推荐使用这种配置方式。

2、在整个后台应用上支持跨域访问

在这个应用程序的范围内支持跨域访问是比较常见的使用方法,而且这种配置有很多实现方式。

2.1、在web.xml中配置

将在上述服务器中的web.xml上配置的filter,配置到自己的工程中。然后加入maven依赖,如下类似:

<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>2.5</version>
</dependency>

这样就完成了对跨域访问请求的支持,如果并不想对所有的请求都支持跨域访问,则可以在Filter的url-pattern中改变匹配到的url地址。

2.2、通过WebMvcConfigurer ###

在Spring中,使用这个接口可以通过定义回调方法来进行一些Spring MVC中要用到的配置,在里面用来支持CORS的方法是addCorsMappings(CorsRegistry registry),我们并不直接使用这个接口而是使用它的抽象实现类WebMvcConfigurerAdapter,这个类中给我们提供了WebMvcConfigurer接口中方法的空实现,我们可以直接填上自己的业务逻辑就可以直接使用。在这个回调方法中的参数是CorsRegistry,这个类可以帮助我们为相应的url地址提供CORS配置,关于这个方法可以放到Application启动类中,也可以单独放到一个类中。

在Application启动类中使用该方法,只需要在Application启动类中加入如下代码即可。

@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/greeting-javaconfig").allowedOrigins("http://localhost:9000");
}
};
}

独自建立新类使用该方法,则需要配置一些注解,如下:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.springboot.demo" })
public class WebConfig extends WebMvcConfigurerAdapter { @Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/*").allowedOrigins("http://localhost:8070");
} }

与在Application启动类中使用相比多了@Configuration@EnableWebMvc注解,这是因为@SpringBootApplication已经包含上述两个注解了,所以不需要重新加入。 
CorsRegistry中调用addmapping后会得到CorsRegistration类,这时候就可以使用链式调用可以对这个CORS配置进行origin、method、header、maxage等的限制,这里就不展开了。

2.3 自定义Filter

所有的方法归根结底就是拦截对接口的访问,所以如果你不想麻烦并且想深入了解CORS到底是怎样工作的,可以通过自定义Filter来实现,其实这也没有什么难的,就是在拦截器上通过对请求和响应加上一些Headers,这里就不说了。

3、在单个接口上支持跨域访问

跨域访问所支持的最小的范围就是在Controller以及对应的方法上,这里使用@CrossOrigin注解来完成相应的配置,首先来看看这个注解的源代码。

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {
String[] DEFAULT_ORIGINS = { "*" };
String[] DEFAULT_ALLOWED_HEADERS = { "*" };
boolean DEFAULT_ALLOW_CREDENTIALS = true;
long DEFAULT_MAX_AGE = 1800; String[] value() default {};
@AliasFor("value")
String[] origins() default {};
String[] allowedHeaders() default {};
String[] exposedHeaders() default {};
RequestMethod[] methods() default {};
String allowCredentials() default "";
long maxAge() default -1;
}

从该注解中可以看到,它可以使用在方法上,也可以使用在类上,并且已经完全覆盖了CORS提出的响应头首部。

  • 使用在类上,一般使用在有@Controller或者@RestController注解的类上,这样在该类上全部遵从该注解提供的关于CORS的配置。
  • 使用在方法上,该CORS的配置只是针对该指定的方法;

默认情况下,@CrossOrigin支持所有的origin和所有的headers来进行跨域访问,而且它所限制的方法是由@Requestmapping中的method属性来提供的。 
如果查看源码的话是可以发现的,在CorsRegistry中使用addMapping()配置映射时,返回的CorsRegistration类中对origin、header、Credentials的配置使用的就是@CrossOrigin的默认配置。实例如下:

@CrossOrigin(origins={"http://localhost:8070"}, methods={RequestMethod.GET, RequestMethod.POST})
@RequestMapping("/")
@ResponseBody
public String getInformation(){
restHandleService.getRestInformation();
return "spring boot";
}

Java Web应用中支持跨域请求的更多相关文章

  1. 【Java Web开发学习】跨域请求

    [Java Web开发学习]跨域请求 ================================================= 1.使用jsonp ===================== ...

  2. Spring Boot Web应用开发 CORS 跨域请求支持:

    Spring Boot Web应用开发 CORS 跨域请求支持: 一.Web开发经常会遇到跨域问题,解决方案有:jsonp,iframe,CORS等等CORS与JSONP相比 1. JSONP只能实现 ...

  3. 在ASP.NET 5应用程序中的跨域请求功能详解

    在ASP.NET 5应用程序中的跨域请求功能详解 浏览器安全阻止了一个网页中向另外一个域提交请求,这个限制叫做同域策咯(same-origin policy),这组织了一个恶意网站从另外一个网站读取敏 ...

  4. 使用Cors在WebApi中实现跨域请求,请求方式为angular的 $http.jsonp

    使用Cors在WebApi中实现跨域请求 第一步,在webapi项目中安装cors 在Web API配置文件中(Global.asax)进行全局配置: public class WebApiAppli ...

  5. IE9 下面, XMLHttpRequest 是不支持跨域请求的解决方法

    在 IE9 下面, XMLHttpRequest 是不支持跨域请求的. IE10 的 XMLHttpRequest 支持跨域, 而 IE8, IE9 需要使用 XDomainRequest 来实现跨域 ...

  6. php中ajax跨域请求---小记

    php中ajax跨域请求---小记   前端时间,遇到的一个问题,情况大约是这样: 原来的写法: 前端js文件中: $.ajax({ type:'get', url:'http://wan.xxx.c ...

  7. IIS配置支持跨域请求

    对于初次在IIS部署网站的同学,很容易忽略或不知道如何配置使其网站支持跨域请求,这里介绍一个最基础的方式,配置HTTP响应标头. 在IIS上选择HTTP响应标头,选择添加自定义响应标头,通常我们会添加 ...

  8. django 实现全局支持跨域请求

    Django 实现允许跨域请求 1.安装django-cors-headers pip install django-cors-headers 2.配置settings.py文件 INSTALLED_ ...

  9. ASP.NET Core-Docs:在 ASP.NET Core 中启用跨域请求(CORS)

    ylbtech-ASP.NET Core-Docs:在 ASP.NET Core 中启用跨域请求(CORS) 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部 1. ...

随机推荐

  1. Angular-1.6 路由 简单使用

    index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  2. IP地址的分类——a,b,c 类是如何划分的【转】

    ip分类已经是耳熟能详了.但是说的都比较繁琐,这里简述一下,便于以后复习. IP地址,一共分成了5类,范围分别如下: A类IP:从0.0.0.0 – 127.255.255.255,共有1677721 ...

  3. man -k : nothing appropriate.

    ➜ workplace man -k zip zip: nothing appropriate. 出现这种情况,是索引库没有建立. man 和 whatis 共用一个索引库的. 我们使用  man w ...

  4. 【转】Java学习---volatile 关键字

    [原文]https://www.toutiao.com/i6591422029323305480/ 前言 不管是在面试还是实际开发中 volatile 都是一个应该掌握的技能. 首先来看看为什么会出现 ...

  5. oracle数据库中如何去除空格

    目前,我所知道的就有两种方法: 一.trim(a)--只能去除字符串左右的空格 select trim(leading from ' ——11—— ') aa from dual; select tr ...

  6. 巧用foxmail同步qq邮箱的通讯录

    如果您企业使用的qq企业邮箱,那么你在web端登陆邮箱并填写收件人时,发现QQ邮箱是可以自动完成,并且中文名称自动完成. 如何在使用foxmail邮件客户端的情况下也同步这些邮箱信息呢?需要七步,看截 ...

  7. Phoenix安装配置

    下载Phoenix     在网站http://phoenix.apache.org/download.html找到对应HBase版本的安装程序,并下载安装包,解压安装程序到指定目录 [root@ha ...

  8. array_map 巧替 foreach

    1.array_reduce( $arr , callable $callback ) 使用回调函数迭代地将数组简化为单一的值. 其中$arr 为输入数组,$callback($result , $v ...

  9. sql !=与null

    在写SQL 条件语句是经常用到 不等于‘<>’的筛选条件,此时要注意此条件会将字段为null的数据也当做满足不等于的条件而将数据筛选掉. 例:表A A1  B1 1 0 2 1 3 NUL ...

  10. HTML5音/视频标签详解

    一.发展历: 早期:<embed>+<object>+文件   问题:不是所有浏览器都支持,而且embed不是标准.   现状:Realplay.window media.Qu ...