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

模拟跨域

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

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

项目结构如下所示:

在com.example.demo路径下新建controller包,并创建TestController:

@Controller
public class TestController {

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

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

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

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>跨域测试</title>
  <script src="http://libs.baidu.com/jquery/1.11.3/jquery.min.js"></script>
</head>
<body>
<div id="hello"></div>
</body>
<script>
  $(function () {
      $.get("http://test.mrbird.cc:8080/hello", function (data) {
          $("#hello").text(data);
      })
  })
</script>
</html>

编辑本地hosts文件,将http://test.mrbird.cc网址映射到127.0.0.1上:

启动项目访问http://localhost:8080/,会发现页面并没有成功显示hello,并且F12观察浏览器控制台会发现其报错了:

这是因为我们在http://localhost:8080/域名下试图访问http://test.mrbird.cc:8080下的hello接口,这就存在跨域问题,接下来我们来解决这个问题。

注解驱动

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

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

我们来改造TestController中的hello方法:

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

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

接口编程

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

com.example.demo路径下新建config包,然后创建WebConfigurer,实现WebMvcConfigurer,重写addCorsMappings默认实现:

@Configuration
public class WebConfigurer implements WebMvcConfigurer {

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

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

过滤器实现

查看官方文档,发现其还提供了基于过滤器的实现方式:

@Bean
public FilterRegistrationBean corsFilter() {
  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.

Spring Boot 中处理跨域的更多相关文章

  1. spring boot:解决cors跨域问题的两种方法(spring boot 2.3.2)

    一,什么是CORS? 1,CORS(跨域资源共享)(CORS,Cross-origin resource sharing), 它是一个 W3C 标准中浏览器技术的规范, 它允许浏览器向非同一个域的服务 ...

  2. Java Spring boot 2.0 跨域问题

    跨域 一个资源会发起一个跨域HTTP请求(Cross-site HTTP request), 当它请求的一个资源是从一个与它本身提供的第一个资源的不同的域名时 . 比如说,域名A(http://dom ...

  3. spring boot之配置跨域

    在启动类中配置 @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override p ...

  4. spring boot项目配置跨域

    1.在项目启动入口类实现 WebMvcConfigurer 接口: @SpringBootApplication public class Application implements WebMvcC ...

  5. 关于 Spring Security OAuth2 中 CORS 跨域问题

    CORS 是一个 W3C 标准,全称是”跨域资源共享”(Cross-origin resource sharing).它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了 AJA ...

  6. Spring Boot中通过CORS解决跨域问题

    今天和小伙伴们来聊一聊通过CORS解决跨域问题. 同源策略 很多人对跨域有一种误解,以为这是前端的事,和后端没关系,其实不是这样的,说到跨域,就不得不说说浏览器的同源策略. 同源策略是由Netscap ...

  7. Spring Boot中使用 Spring Security 构建权限系统

    Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配置的Bean,为应用系统提供声明式的安全 ...

  8. Spring Boot中只能有一个WebMvcConfigurationSupport配置类

    首先将结论写文章的最前面,一个项目中只能有一个继承WebMvcConfigurationSupport的@Configuration类(使用@EnableMvc效果相同),如果存在多个这样的类,只有一 ...

  9. Springboot中关于跨域问题的一种解决方法

    前后端分离开发中,跨域问题是很常见的一种问题.本文主要是解决 springboot 项目跨域访问的一种方法,其他 javaweb 项目也可参考. 1.首先要了解什么是跨域 由于前后端分离开发中前端页面 ...

  10. Spring Boot 中 Redis 的使用

    Spring Boot 对常用的数据库支持外,对 Nosql 数据库也进行了封装自动化,如Redis.MongoDB等,本文主要介绍Redis的使用. Redis 介绍 Redis 是目前业界使用最广 ...

随机推荐

  1. 【git】7.5 git工具-搜索

    资料来源: (1) https://git-scm.com/book/zh/v2/Git-%E5%B7%A5%E5%85%B7-%E6%90%9C%E7%B4%A2 1.git grep 注1:使用g ...

  2. pycharm永久激活码(亲测好用)

    引用自某不知名大佬,在此致谢,获取激活码链接如下: https://www.ajihuo.com/pycharm/4197.html

  3. centos7.2下配置dhcp v4或v6服务

    1.centos7.2下配置dhcp v4或v6服务 安装dhcp-server centos7及以前版本的操作系统使用命令: yum install dhcp centos8使用命令: yum in ...

  4. JMeter 三- Run JMeter in non-GUI mode

    Run Jmeter in non-GUI mode: 1. Swith to \Jmeter\bin 2. run "jmeter -n -t E:\JmeterforLoadGenesi ...

  5. mplfinance常用方法

    一.主题相关 查看可用预设主题 mpf.available_styles() 默认的主题包括:'binance','blueskies','brasil','charles','checkers',' ...

  6. 不安全的权限 0644,建议使用 0600 虚拟机无法分配内存 virtual memory exhausted: Cannot allocate memory

    我都不知道我写了啥,自己都很混乱 aoteman@aoteman-virtual-machine:/tmp$ sudo -s #进入root用户模式 [sudo] aoteman 的密码: 12对不起 ...

  7. nginx配置透明代理

    来自:https://blog.csdn.net/weixin_34072458/article/details/91677177 user nginx; worker_processes auto; ...

  8. Git 初始命令行

    命令行指令 Git 全局设置 git config --global user.name "Administrator" git config --global user.emai ...

  9. 为什么JAVA中(byte)128结果为-128;(byte)-129结果为127

    为什么JAVA中(byte)128结果为-128;(byte)-129结果为127 在JAVA中默认的整型为int型,int型占4个字节,为32位.byte占一个字节为8位. JAVA中的二进制都是采 ...

  10. 实现MybatisPlus乐观锁

    1.实体类中添加version字段及相关注解 @Version@TableField(fill = FieldFill.INSERT)//第一次添加数据时使其有个默认值1private Integer ...