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. Java基础__06.注解和反射

    注解 什么是注解? 1.注解:annocation,是从JDK5.0开始引进入的新技术. 2.注解的作用: 不是程序本身,可以对程序做出解释,这一点和注释一样: 可以被其他程序读取,这点是和注释的区别 ...

  2. MinGW、Linux GNU、MSVC编译和链接动态库的分析

    这几天研究CMake跨平台项目嘛,用了以下几种编译器: VS2019(MSVC) Linux GNU MinGW 编译之后发现链接动态库发现以下问题: VS2019中如果直接链接CMakeLists. ...

  3. 常用的Shell实用脚本

    1.检测两台服务器指定目录下的文件的一致性 #!/bin/bash######################################检测两台服务器指定目录下的文件一致性########### ...

  4. 解决ubuntu18环境matplotlib无法正常显示中文

    首先看看系统装了中文字体没?命令: fc-list :lang=zh 如果没安装,需要去下载或者从win复制一份到ubuntu, 在/usr/share/fonts文件夹下创建一个chinese文件夹 ...

  5. python批量更改文件名并移动到新的文件夹

    python批量更改文件名并移动到新的文件夹 前言: 1. 这里的代码以批量命名如: 路径"E:\下载\1\xxxx.mp4"."E:\下载\2\xxxx.mp4&quo ...

  6. SPI接口

    串行外设接口(Serial Peripheral Interface)是一种同步外设接口,它可以使单片机与各种外围设备以串行方式进行通信以交换信息.SPI最早是Motorola公司提出的全双工三线同步 ...

  7. KVM虚拟机迁移至VMWare ESXi

    需求 由于服务器迁移,为维护方便,将统一使用vmware 平台管理虚拟机,因此需将kvm 虚拟机统一迁至vmware kvm 磁盘镜像转换 查看虚拟机 # virsh list --all Id Na ...

  8. SQL中使用JOIN时,过滤条件的位置

    sql语句 (SELECT * FROM t1 WHERE {subquery_where_condition}) a JOIN (SELECT * FROM t2 WHERE {subquery_w ...

  9. (Jmeter笔记)jmeter连接数据库(mysql)

    下载mysql连接驱动 地址:https://dev.mysql.com/downloads/connector/j/ ****把mysql连接驱动放在Jmeter/lib目录下**** >&g ...

  10. jmeter非GUI模式运行-单节点

    jmeter有自己的GUI页面,但是当线程数很多或者现在有很多的测试场景都是基于linux下进行压测,这时我们可以使用jmeter的命令行方式来执行测试,该篇文章介绍jmeter单节点命令运行方式. ...