SpringBoot 配置CORS

前言:CORS相关介绍可以查看CORS ———— 跨域解决方案 ,这里记录下SpringBoot如何使用CORS解决跨域资源共享问题。以下使用的SpringBoot版本是 2.0.5.RELEASE。

 

一、介绍

Spring官方介绍,SpringMVC从4.2版本开始就支持CORS。在Spring中,使用@CrossOrigin注解,可以在controller方法中使用,而不要其他任何配置;或者在全局配置中,可以通过注册一个WebMvcConfigurer Bean,并使用addCorsMappings(CorsRegistry) 来定义。

SpringBoot 介绍 : https://docs.spring.io/spring-boot/docs/2.0.5.RELEASE/reference/htmlsingle/#boot-features-cors

Spring 4.2版本介绍:https://docs.spring.io/spring/docs/4.2.0.RELEASE/spring-framework-reference/htmlsingle/#cors

 

二、CrossOrigin注解

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {

	/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
	@Deprecated
	String[] DEFAULT_ORIGINS = { "*" };

	/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
	@Deprecated
	String[] DEFAULT_ALLOWED_HEADERS = { "*" };

	/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
	@Deprecated
	boolean DEFAULT_ALLOW_CREDENTIALS = false;

	/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
	@Deprecated
	long DEFAULT_MAX_AGE = 1800;


	/**
	 * Alias for {@link #origins}.
	 */
	@AliasFor("origins")
	String[] value() default {};

	/**
	 * The list of allowed origins that be specific origins, e.g.
	 * {@code "http://domain1.com"}, or {@code "*"} for all origins.
	 * 

A matched origin is listed in the {@code Access-Control-Allow-Origin} * response header of preflight actual CORS requests. *

By default all origins are allowed. *

Note: CORS checks use values from "Forwarded" * (RFC 7239), * "X-Forwarded-Host", "X-Forwarded-Port", and "X-Forwarded-Proto" headers, * if present, in order to reflect the client-originated address. * Consider using the {@code ForwardedHeaderFilter} in order to choose from a * central place whether to extract and use, or to discard such headers. * See the Spring Framework reference for more on this filter. * @see #value */ @AliasFor("value") String[] origins() default {}; /** * The list of request headers that are permitted in actual requests, * possibly {@code "*"} to allow all headers. *

Allowed headers are listed in the {@code Access-Control-Allow-Headers} * response header of preflight requests. *

A header name is not required to be listed if it is one of: * {@code Cache-Control}, {@code Content-Language}, {@code Expires}, * {@code Last-Modified}, or {@code Pragma} as per the CORS spec. *

By default all requested headers are allowed. */ String[] allowedHeaders() default {}; /** * The List of response headers that the user-agent will allow the client * to access on an actual response, other than "simple" headers, i.e. * {@code Cache-Control}, {@code Content-Language}, {@code Content-Type}, * {@code Expires}, {@code Last-Modified}, or {@code Pragma}, *

Exposed headers are listed in the {@code Access-Control-Expose-Headers} * response header of actual CORS requests. *

By default no headers are listed as exposed. */ String[] exposedHeaders() default {}; /** * The list of supported HTTP request methods. *

By default the supported methods are the same as the ones to which a * controller method is mapped. */ RequestMethod[] methods() default {}; /** * Whether the browser should send credentials, such as cookies along with * cross domain requests, to the annotated endpoint. The configured value is * set on the {@code Access-Control-Allow-Credentials} response header of * preflight requests. *

NOTE: Be aware that this option establishes a high * level of trust with the configured domains and also increases the surface * attack of the web application by exposing sensitive user-specific * information such as cookies and CSRF tokens. *

By default this is not set in which case the * {@code Access-Control-Allow-Credentials} header is also not set and * credentials are therefore not allowed. */ String allowCredentials() default ""; /** * The maximum age (in seconds) of the cache duration for preflight responses. *

This property controls the value of the {@code Access-Control-Max-Age} * response header of preflight requests. *

Setting this to a reasonable value can reduce the number of preflight * request/response interactions required by the browser. * A negative value means undefined. *

By default this is set to {@code 1800} seconds (30 minutes). */ long maxAge() default -1; }

 

三、具体使用

1、method配置

@CrossOrigin(origins = "http://localhost:8080", methods = RequestMethod.POST)
@RequestMapping(value = "/single", method = RequestMethod.POST)
public String single() {
    return "{\"name\":\"single\"}";
}

直接在方法级上添加@CrossOrigin注解启用CORS,默认情况下,允许@RequestMapping注释中所指定的所有的Origins和Methods。

 

2、controller配置

@CrossOrigin(origins = "http://localhost:8080", methods = { RequestMethod.GET})
@RestController()
@RequestMapping("/test")
public class TestController {

    @RequestMapping(value = "/common", method = RequestMethod.GET)
    public String common() {
        return "{\"name\":\"common\"}";
    }

    @RequestMapping("test")
    public String test() {
        return "test";
    }
    
    @RequestMapping(value = "other", method = RequestMethod.POST)
    public String other() {
        return "other";
    }
}

只需要在controller上添加@CrossOrigin注解启用CORS。此时该controller里的common,test两个方法都支持跨域,但是other不支持,因为method不支持。

 

3、controller和method共存

@CrossOrigin(methods = RequestMethod.GET)
@RestController()
@RequestMapping("/test")
public class TestController {

    /**
     * 
     * @return
     * @Description: 单接口支持跨域
     */
    @CrossOrigin(origins = "http://localhost:8080", methods = RequestMethod.POST)
    @RequestMapping(value = "/single", method = RequestMethod.POST)
    public String single() {
        return "{\"name\":\"single\"}";
    }

    /**
     * 
     * @return
     * @Description: 该controller下的公共支持跨域
     */
    @RequestMapping(value = "/common", method = RequestMethod.GET)
    public String common() {
        return "{\"name\":\"common\"}";
    }

    @RequestMapping("test")
    public String test() {
        return "test";
    }
}

controller和method同时开启注解,但是实际以method的为主。

 

4、全局配置

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter{

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }

 
}

只需要添加一个配置文件,重写addCorsMappings方法,但是,在2.0.5版本中, WebMvcConfigurerAdapter已被废弃。

可以通过注册一个WebMvcConfigurer bean:

@Configuration
public class WebConfig {

    @Bean
    public WebMvcConfigurer configurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**");
            }

        };
    }

}

 这里默认所有方法都跨域,并且GET, POST,HEAD是被允许的,如果需要自定义,只需要配置即可:

SpringBoot 配置CORS_第1张图片

比如:

@Configuration
public class WebConfig {

    @Bean
    public WebMvcConfigurer configurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/common/**")
                    .allowedOrigins("http://localhost:8080")
                    .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTION")
                    .maxAge(100);
            }

        };
    }

}

当全局配置,controller和method都存在时,以最小力度为准。

 

5、全局过滤器配置

    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Bean
    public FilterRegistrationBean filter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.addAllowedOrigin("http://localhost:8080");
        configuration.addAllowedMethod("GET");
        configuration.addAllowedMethod("POST");
        configuration.addAllowedMethod("OPTION");
        configuration.addAllowedMethod("PUT");
        source.registerCorsConfiguration("/**", configuration);
        return new FilterRegistrationBean(new CorsFilter(source));

    }

跟4类似。。。。

 

总结:SpringBoot配置CORS非常方便,也很灵活,比自己用servlet定义快捷方便,最主要的是,即使使用简单请求,跨域请求失败,也不会走到实际的业务流程中。 

你可能感兴趣的:(SpringBoot)