SpringBoot 中处理跨域

HTML 5中新增的跨域资源访问(Cross-Origin Resource Sharing)特性可以让我们在开发后端系统的时候决定资源是否允许被跨域访问。所谓跨域指的是域名不同或者端口不同或者协议不同,比如当从lconcise.top网站访问lconcise.top:9090网站资源就会存在跨域问题。Spring从4.2版本开始就提供了跨域的支持,开箱即用。这里介绍如何在Spring Boot开发中解决跨域的问题,主要分为注解驱动和接口编程的方式。

  1. 模拟跨域
  2. 注解驱动
  3. 接口编程
  4. 过滤器实现
  5. Actuator跨域

模拟跨域

要解决跨域问题,我们就得先模拟一个跨域情景。新建Spring Boot项目,并引如下依赖:

        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-thymeleaf
        

创建DemoController类:

@Controller
public class DemoController {

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

    @GetMapping("/hello")
    @ResponseBody
    public String hello() {
        return "hello";
    }
}

然后在resources/templates下新建index.html:




    
    跨域测试
    


编辑本地hosts文件,将域名lconcise.top映射到127.0.0.1上:

image.png

启动项目访问http://127.0.0.1:9090/index,会发现页面并没有成功显示hello,并且F12观察浏览器控制台会发现其报错了:
image.png
这是因为我们在http://127.0.0.1:9090/index域名下试图访问http://lconcise.top:9090/index下的hello接口,这就存在跨域问题,接下来我们来解决这个问题。

注解驱动

Spring 4.2后提供了@CrossOrigin注解,该注解可以标注于方法或者类上,包含了以下属性:

属性 含义
value 指定所支持域的集合,表示所有域都支持,默认值为。这些值对应HTTP请求头中的Access-Control-Allow-Origin
origins 同value
allowedHeaders 允许请求头中的header,默认都支持
exposedHeaders 响应头中允许访问的header,默认为空
methods 支持请求的方法,比如GET,POST,PUT等,默认和Controller中的方法上标注的一致。
allowCredentials 是否允许cookie随请求发送,使用时必须指定具体的域
maxAge 预请求的结果的有效期,默认30分钟

我们来改造DemoController中hello 方法。

    @GetMapping("/hello")
    @ResponseBody
    @CrossOrigin(value = "*")
    public String hello() {
        return "hello";
    }

表示允许所有域都支持,重启项目,再次访问http://127.0.0.1:9090/index

image.png

接口编程

除了使用@CrossOrigin注解外,我们可以使用接口编程的方式进行统一配置。

创建WebConfigurer,实现WebMvcConfigurer,重写addCorsMappings默认实现:

@Configuration
public class WebConfigurer implements WebMvcConfigurer {

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

上面配置表示允许所有请求支持跨域访问,并且不限定域,但是支持持GET方法。将hello方法上的@CrossOrigin注解注释掉,重启项目,再次访问,结果也是OK的。

过滤器实现

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean registFilter() {
        org.springframework.web.cors.UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
}

Actuator跨域

如果项目里集成了Actuator相关功能,其暴露的接口也支持跨域,只需要在配置文件中添加如下配置即可:

ENDPOINTS CORS CONFIGURATION (CorsEndpointProperties)

management.endpoints.web.cors.allow-credentials= # Whether credentials are supported. When not set, credentials are not supported.
management.endpoints.web.cors.allowed-headers= # Comma-separated list of headers to allow in a request. '*' allows all headers.
management.endpoints.web.cors.allowed-methods= # Comma-separated list of methods to allow. '*' allows all methods. When not set, defaults to GET.
management.endpoints.web.cors.allowed-origins= # Comma-separated list of origins to allow. '*' allows all origins. When not set, CORS support is disabled.
management.endpoints.web.cors.exposed-headers= # Comma-separated list of headers to include in a response.
management.endpoints.web.cors.max-age=1800s # How long the response from a pre-flight request can be cached by clients. If a duration suffix is not specified, seconds will be used.

源码:https://github.com/lbshold/springboot/tree/master/Spring-Boot-CORS-Support

参考文章:https://mrbird.cc/Spring-Boot-Deal-CORS.html

你可能感兴趣的:(SpringBoot 中处理跨域)