SpringBoot 配置 跨域支持

👆关注微信公众号,获取更多编程内容


跨域资源共享(CORS,请求协议,请求地址,请求端口三者必须相同才是同一服务器,否则都要进行跨域操作)标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。

常见的CORS的HTTP头

其根本是在请求响应结果中添加响应头,来表名服务支持CORS,因此常见的CORS头如下:

名称 示例 作用
Access-Control-Allow-Origin https://www.zhoutao123.com 表明它允许"www.zhoutao123.com"发起跨域请求
Access-Control-Max-Age 3628800 表明在3628800秒内,不需要再发送预检验请求
Access-Control-Allow-Methods GET,PUT, DELETE 允许GET、PUT、DELETE的外域请求
Access-Control-Allow-Headers content-type 允许跨域请求包含content-type头

CORS执行流程

CORS在首次请求跨域服务器之前,都要进行预检请求 ,会首先发送一个OPTIONS请求检查是否支持CORS,待服务器响应之后,在进行后续的操作,具体流程图下,当然并不是每个请求都会发送OPTIONS请求,在确认支持CORS之后,浏览器会把验证结果缓存下来,缓存的有效时间可以通过 Access-Control-Max-Age 来控制:

![](https://www.zhoutao123.com/wp-content/uploads/2018/06/prelight-283x300.png)

预检请求重定向

大多数浏览器不支持针对于预检请求的重定向。如果一个预检请求发生了重定向,浏览器将报告错误:

The request was redirected to 'https://example.com/foo', which is disallowed for cross-origin requests that require preflight

Request requires preflight, which is disallowed to follow cross-origin redirect

CORS 最初要求该行为,不过在后续的修订中废弃了这一要求。不过我们还是尽量不要对OPTIONS预检请求做重定向处理.

  • 注意:因为CORS在发送真正的请求之前会发送OPTIONS请求,以此来验证服务器是否支持跨域,此次预检请求不携带任何真正请求的参数,当前也不包括我们设定的token参数,因此如果你的Spring应用或者其他应用在拦截器上做了验证,请注意不要拦截OPTIONS请求,否则CORS支持会开启失败.

SpringBoot开启CORS

非全局配置

So that the RESTful web service will include CORS access control headers in its response, you just have to add a @CrossOrigin annotation to the handler method

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {
	
	//允许跨域的服务器
	@AliasFor("origins")
	String[] value() default {};
	
	//和上面是一样的 AliasFor
	@AliasFor("value")
	String[] origins() default {};

	//允许头部
	String[] allowedHeaders() default {};

	String[] exposedHeaders() default {};
	
	/**
	 * The list of supported HTTP request methods.
	 * <p>By default the supported methods are the same as the ones to which a
	 * controller method is mapped.
	 */
	RequestMethod[] methods() default {};
	
	String allowCredentials() default "";
	
	/**
	 * The maximum age (in seconds) of the cache duration for preflight responses.
	 * <p>This property controls the value of the {@code Access-Control-Max-Age}
	 * response header of preflight requests.
	 * <p>Setting this to a reasonable value can reduce the number of preflight
	 * request/response interactions required by the browser.
	 * A negative value means <em>undefined</em>.
	 * <p>By default this is set to {@code 1800} seconds (30 minutes).
	 */
	long maxAge() default -1;
}

只要在SpringBoot的Mapper()接口中添加并配置此注解即可

	//根据CrossOrigin的注释可以再请求参数的不存在的时候,CORS支持的方法和Mapper支持的方法一致
    @CrossOrigin(origins = "http://localhost:9000")
    @GetMapping("/test")
    public Greeting greeting(@RequestParam(required=false, defaultValue="World") String name) {
        System.out.println("==== in tesing ====");
        return "SUCCESS";
    }

全局配置

在大量接口需要开启CORS支持的时候,上面的方式显然不适合操作,因此Spring提供了全局配置CORS支持的方式。

  @Bean
  @SuppressWarnings("deprecation")
  public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurerAdapter() {
      @Override
      public void addCorsMappings(CorsRegistry registry) {
        log.info("CORS 配置参数 origins = {}  url = {}", allowedOrigins, allowedUrl);
        registry
            .addMapping("/**")
            .allowedMethods("GET", "POST", "PATCH", "DELETE", "PUT", "OPTIONS")
            .allowedOrigins("http://localhost:9090");
      }
    };
  }
posted @ 2019-02-15 10:26  燕归来兮  阅读(1968)  评论(0编辑  收藏  举报