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. cAPP.h头文件

    前言 最近几天闲的没事,写了一个可以用来写简单的app程序的头文件,分享给大家! 头文库 #ifndef CAPP_H #define CAPP_H #include<bits/stdc++.h ...

  2. 《Python深度学习》《卷积神经网络的可视化》精读

    对于大多数深度学习模型,模型学到的表示都难以用人类可以理解的方式提取和呈现.但对于卷积神经网络来说,我们可以很容易第提取模型学习到的表示形式,并以此加深对卷积神经网络模型运作原理的理解. 这篇文章的内 ...

  3. zabbix中文显示乱码解决

    问题zabbix使用中文显示,"监测-->图形"查看资源使用情况时会有乱码 解决问题1.修改配置文件(文件位置:$zabbix_path/include/defines.in ...

  4. tvm中使用了xgboost库中的_fmt_metric

    _fmt_metric这个xgboost的回调函数已经被遗弃了. 为了能跑起来tvm,可以pip install xgboost==1.5.0

  5. 监控本机环境生成SQL脚本

    在开发工作中我们客户端连接 测试服务器开发工作,往往很多人操作数据库,如何甄别出自己操作 方法一: 在程序配置节点设置App节点,譬如: <add name="ModelEntitie ...

  6. Uncaught ReferenceError: Vue is not defined(之一)

    报错信息 Uncaught ReferenceError- Vue is not defined 报错代码示例 <body> <div id="app"> ...

  7. 'umi' 不是内部或外部命令,也不是可运行的程序 或批处理文件或umi: command not found

    问题 'umi' 不是内部或外部命令,也不是可运行的程序 或批处理文件或umi: command not found 解决方法 参考链接:https://blog.csdn.net/weixin_40 ...

  8. 1144. 递减元素使数组呈锯齿状 (Medium)

    问题描述 1144. 递减元素使数组呈锯齿状 (Medium) 给你一个整数数组 nums,每次 操作 会从中选择一个元素并 将该元素的值减少 1. 如果符合下列情况之一,则数组 A 就是 锯齿数组: ...

  9. FTP为什么越来越不好用了?要如何替代?

    FTP相信很多人都不陌生,作为世界范围内第一个文件传输协议,FTP解决了互联网文件传输需求,至今已被广泛使用30多年.但很多人现在慢慢发现,FTP越来越不好用了,或者说越来越无法满足自己需求了,这是为 ...

  10. tp3.2 写入日志

    function logs($content, $subDir = ''){ $subDir = trim($subDir, '/\\'); if (empty($content)) return f ...