要知道跨域请求就要先了解同源策略,那么什么是同源?什么是不同源?简单来说就是,如果两个资源,包括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";
}

相关文章:http://blog.csdn.net/lmy86263/article/details/51724221

Java Web解决跨域请求的更多相关文章

  1. js中ajax如何解决跨域请求

    js中ajax如何解决跨域请求,在讲这个问题之前先解释几个名词 1.跨域请求 所有的浏览器都是同源策略,这个策略能保证页面脚本资源和cookie安全 ,浏览器隔离了来自不同源的请求,防上跨域不安全的操 ...

  2. Ajax 调用webservice 解决跨域请求和发布到服务器后本地调用成功外网失败的问题

        webservice 代码 /// <summary> /// MESService 的摘要说明 /// </summary> [WebService(Namespac ...

  3. XMLHttpRequest.withCredentials 解决跨域请求头无Cookie的问题

    查看原文 XMLHttpRequest.withCredentials  属性是一个Boolean类型,它指示了是否该使用类似cookies,authorization headers(头部授权)或者 ...

  4. 外部调用mvc的api方法时,如何解决跨域请求问题?

    首先,创建一个mvc项目(包含webapi),我们模拟一个场景 1)在项目的Controller 创建一个WeiXinApiController public class WeiXinApiContr ...

  5. SpringBoot解决跨域请求拦截

    前言 同源策略:判断是否是同源的,主要看这三点,协议,ip,端口. 同源策略就是浏览器出于网站安全性的考虑,限制不同源之间的资源相互访问的一种政策. 比如在域名https://www.baidu.co ...

  6. Django使用jsonp和cors解决跨域请求问题

    1.使用jsonp的方式解决跨域请求的问题 我启动两个django项目,然后使用的端口不一样,在项目1中通过ajax发请求给项目2,然后接受项目2发送过来的数据 先看项目1的ajax的代码 $(&qu ...

  7. 使用SpringMVC的@CrossOrigin注解解决跨域请求问题

    跨域问题,通俗说就是用ajax请求其他站点的接口,浏览器默认是不允许的.同源策略(Same-orgin policy)限制了一个源(orgin)中加载脚本或脚本与来自其他源(orgin)中资源的交互方 ...

  8. JSONP方法解决跨域请求

    Ajax跨域请求的问题 跨域:跨域名, 一个域名下的文件去请求了和他不一样的域名下的资源文件(注意是请求文件,而不是数据接口),那么就会产生跨域请求,下面来写一个ajax来跨域请求的例子 <!D ...

  9. 解决web资源跨域请求问题

    参考地址: http://my.oschina.net/lichaoqiang/blog/317823 在浏览器请求中,出现跨域访问资源的问题,我们肯定会遇到.如果跨域请求被阻止,有可能导致css.j ...

随机推荐

  1. (转)通过注册表修改VC6.0的字体

    出处:http://www.cnblogs.com/PocketZ 在VC6.0下更改字体,我们一般通过菜单-Tools-Options-Format来更改 但在我的win7 64位系统下这一选项下的 ...

  2. Mysql 数据库复制

    Mysql 数据库复制 数据库复制是一种同步手段,主库向一台或多台数据库同步数据. 这个功能我自己曾经用uts数据传输工具实现过! 现在学习了一下mysql数据库复制的其他方式 第一个就是最简单的使用 ...

  3. paiza

    <?php $str1 = ('paiza'); $str2 = ('apple'); $str3 = ('letter'); function bigTower($str1, $str2, $ ...

  4. sass 和less 分别在循环 和超出省略方面的区别!

    这两天在迁项目,新项目支持less预处理器,之前是采用的sass,就出现一些冲突,好在有对应的转换方式,重点说下 我遇到的2个问题 1:超出省略 sass: 声明: 在需要的地方: less: 在使用 ...

  5. java中抽象类是否可以继承实体类?

    一道java 常见面试题,网上找到的几乎每个 java 面试笔试题大全或集锦里都能找到这道题. 题目如下:问: 抽象类是否可继承实体类 (concrete class) 答: 抽象类是可以继承实体类, ...

  6. windows server 2003产生的 Minidmp蓝屏文件分析求助

    在机房运行的四台服务器中均出现了蓝屏dmp文件,经过整理发现CDMS主备服务器最近(2018年1月开始)蓝屏的dmp很多.经过自己的学习分析发现不足以找到先关的原因和处理方法,希望得到大牛们的帮助.以 ...

  7. C#生成缩略图,C#给图片添加水印

    生成缩略图 #region 生成缩略图 /// <summary> /// 生成缩略图 /// </summary> /// <param name="orig ...

  8. 【perl】simpleHTTP

    类似Python SimpleHTTPServer #!/usr/bin/perl # https://metacpan.org/pod/HTTP::Server::Simple # https:// ...

  9. C机器级移位,编码表示 无符号编码表示,有符号编码表示一般最常见的方式是补码

    C机器级移位,编码表示 无符号编码表示,有符号编码表示一般最常见的方式是补码  w位补码所能表示的值范围是 首先我们得心知 补码的最高有效位是符号位,当符号位位1是表示的是负值,当符号位是0是,表示的 ...

  10. 【转】配置Exchange 2010 服务器(二)Exchange2010证书配置

    原文链接:http://blog.51cto.com/shubao/788562 (一)架设证书服务器 (二)Exchange2010申请证书 (三)证书服务器导入Exchange服务器受信任根证书 ...