同源策略是浏览器的一个安全限制,要求域名、协议、端口相同,如果不同则没办法进行数据交互。
而跨域配置,则是为了解除这方面的限制。
前后端分离的情况下,因为需要分开部署,后台开发基本都需要进行跨域配置了。
(当然,这也可以在 nginx 上处理,这里就不展开讨论了)

spring 提供的跨域拦截器是 CorsFilter,与 CorsFilter 强关联的类是 UrlBasedCorsConfigurationSource。

跨域配置实体类

参数介绍可以看代码注释

 * 跨域配置一览:
* <p>
* Access-Control-Allow-Origin: 允许访问的域名
* Access-Control-Allow-Methods: 允许访问的请求方式
* Access-Control-Allow-Headers: 允许使用的Header
* Access-Control-Allow-Credentials: 是否允许用户发送、处理Cookie
* Access-Control-Max-Age: 预检有效期,单位为秒。有效期内,不需要重复发送预检请求
* Access-Control-Expose-Headers: Header白名单,不设置的话,客户端读不到header的内容
*
* @author Mr.css
* @date 2022-03-09 16:55
*/
public class CrossDomain implements Serializable {
private static final long serialVersionUID = -3682297338044962128L;
/**
* 路径,Controller提供的接口
*/
@Length(max = 64)
@Schema(description = "路径")
private String antPath;
/**
* 允许访问的IP
*/
@Length(max = 64)
@Schema(description = "允许访问的IP")
private String allowedOrigin;
/**
* 开放请求头
*/
@Length(max = 64)
@Schema(description = "允许的请求头")
private String allowedHeader;
/**
* 开放请求方式
*/
@Length(max = 32)
@Schema(description = "允许的请求方式")
private String allowedMethod;
/**
* 白名单Header
*/
@Length(max = 64)
@Schema(description = "白名单Header")
private String exposedHeader;
/**
* 预检请求有效期
*/
@Schema(description = "预检请求有效期")
private Integer maxAge;
/**
* 允许携带凭证
*/
@Schema(description = "允许携带凭证")
private Boolean allowCredentials; // 省略getter/setter

Yml配置

YML配置方式,与实体类字段对应

boot-cross-domain:
config:
allowed-origin: 'http://localhost:8080'
ant-path: '/**'
allowed-header: '*'
allowed-method: '*'
allow-credentials: true

默认配置方式(单个跨域)

如果客户端不多,默认的配置就已经很好用了。

import cn.seaboot.common.core.CommonUtils;
import cn.seaboot.common.lang.Warning;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter; /**
* 跨域配置
*
* @author Mr.css
* @date 2020-07-08 09:04
**/
@Configuration
@ConfigurationProperties(prefix = "boot-cross-domain")
public class CrossDomainStarter {
private Logger logger = LoggerFactory.getLogger(CrossDomainStarter.class); private CrossDomain config; public CrossDomain getConfig() {
return config;
} public void setConfig(CrossDomain config) {
this.config = config;
} @Bean
@SuppressWarnings(Warning.UNCHECKED)
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
logger.info("【Configuration】Cross domain setting: start...");
CorsConfiguration corsConfiguration = new CorsConfiguration();
String origin = config.getAllowedOrigin();
if (origin.endsWith("/") || origin.endsWith("\\")) {
origin = origin.substring(0, origin.length() - 2);
}
corsConfiguration.addAllowedOrigin(origin); //AllowedHeader
String allowHeader = config.getAllowedHeader();
if (CommonUtils.isNotEmpty(allowHeader)) {
for (String header : allowHeader.split(",")) {
corsConfiguration.addAllowedHeader(header);
}
} //AllowedMethod
String allowedMethod = config.getAllowedMethod();
if (CommonUtils.isNotEmpty(allowedMethod)) {
for (String method : allowedMethod.split(",")) {
corsConfiguration.addAllowedMethod(method);
}
}//AllowedHeader
String exposedHeader = config.getExposedHeader();
if (CommonUtils.isNotEmpty(exposedHeader)) {
for (String header : exposedHeader.split(",")) {
corsConfiguration.addExposedHeader(header);
}
} //MaxAge
if (config.getMaxAge() != null) {
corsConfiguration.setMaxAge(config.getMaxAge().longValue());
} //AllowCredentials
if (config.getAllowCredentials() != null) {
corsConfiguration.setAllowCredentials(config.getAllowCredentials());
}
logger.info("Cross domain using config: {}", config);
source.registerCorsConfiguration(config.getAntPath(), corsConfiguration);
logger.info("【Configuration】Cross domain setting: finish");
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new CorsFilter(source));
filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filterRegistrationBean;
}
}

配置多个跨域

 * Access-Control-Allow-Origin:         允许访问的域名
* Access-Control-Allow-Methods: 允许访问的请求方式
* Access-Control-Allow-Headers: 允许使用的Header
* Access-Control-Allow-Credentials: 是否允许用户发送、处理Cookie

这些参数本身就可以配置多个,用逗号分隔即可。

增加更多的跨域配置

逗号拼接的方式,决定了功能上限,如果有很多个客户端,配置起来就会很乱,比如说,我有10个客户端要配置怎么办?
这种场景下,通常会选择直接使用通配符 *,放开跨域拦截,通过业务控制,或者通过鉴权系统控制。

虽说如此,强行实现一波,应当如何?

直接看源码,上面我们用到了 UrlBasedCorsConfigurationSource,
UrlBasedCorsConfigurationSource 的父类是 CorsConfigurationSource,
这个类,相当于Dao,参数是 request,根据 request 的内容查找对应的跨域配置。

我们可以自己实现一个 CorsConfigurationSource。
代码贴出来显得文章篇幅太大,而且代码功能单一,就是配置查询,这次就简单地说明一下,下面提供了伪代码作为参考。

    @Override
@Nullable
public CorsConfiguration getCorsConfiguration(@NotNull HttpServletRequest request) {
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
// 获取客户端域名
String origin = request.getHeader(HttpHeaders.ORIGIN);
// TODO: 根据客户端的域名,查找CorsConfiguration配置
return null;
}

SpringBoot(十五)单个以及多个跨域的配置方法的更多相关文章

  1. springboot(十八):CORS方式实现跨域

    资料 https://www.cnblogs.com/toutou/p/9843588.html

  2. SpringBoot 优雅配置跨域多种方式及Spring Security跨域访问配置的坑

    前言 最近在做项目的时候,基于前后端分离的权限管理系统,后台使用 Spring Security 作为权限控制管理, 然后在前端接口访问时候涉及到跨域,但我怎么配置跨域也没有生效,这里有一个坑,在使用 ...

  3. vue+springboot前后端分离实现单点登录跨域问题处理

    最近在做一个后台管理系统,前端是用时下火热的vue.js,后台是基于springboot的.因为后台系统没有登录功能,但是公司要求统一登录,登录认证统一使用.net项目组的认证系统.那就意味着做单点登 ...

  4. Springboot实现filter拦截token验证和跨域

    背景 web验证授权合法的一般分为下面几种 使用session作为验证合法用户访问的验证方式 使用自己实现的token 使用OCA标准 在使用API接口授权验证时,token是自定义的方式实现起来不需 ...

  5. Web API(五):Web API跨域问题

    一.什么是跨域问题 跨域:指的是浏览器不能执行其他网站的脚本.是由浏览器的同源策略造成的,是浏览器施加的安全限制.(服务端可以正常接收浏览器发生的请求,也可以正常返回,但是由于浏览器的安全策略,浏览器 ...

  6. 两种解决springboot 跨域问题的方法示例

    两种解决springboot 跨域问题的方法示例,哪种方法看情况而定,自己选择.社会Boolean哥,人狠话不多,直接上代码. 第一种实现方式:       此种方式做全局配置,用起来更方便,但是无法 ...

  7. 浅谈配置chrome浏览器允许跨域操作的方法

    浅谈配置chrome浏览器允许跨域操作的方法 一:(Lying人生感悟.可忽略) 最近有一天,对着镜子,发现满脸疲惫.脸色蜡黄.头发蓬松.眼神空洞,于是痛诉着说生活的不如意,工作没激情,工资不高,一个 ...

  8. Nginx反向代理、CORS、JSONP等跨域请求解决方法总结

    由于 Javascript 同源策略的存在使得一个源中加载来自其它源中资源的行为受到了限制.即会出现跨域请求禁止. 通俗一点说就是如果存在协议.域名.端口或者子域名不同服务端,或一者为IP地址,一者为 ...

  9. spring mvc \ spring boot 允许跨域请求 配置类

    用@Component 注释下,随便放个地方就可以了 package com.chinaws.wsarchivesserver.core.config; import org.springframew ...

  10. Web Api跨域访问配置及调用示例

    1.Web Api跨域访问配置. 在Web.config中的system.webServer内添加以下代码: <httpProtocol> <customHeaders> &l ...

随机推荐

  1. swiper弹出窗口居中效果css

    position: absolute; width: 800px; left: 50%; top: 50%; transform: translate(-50%, -50%);

  2. Postgresql通过pg_waldump来分析pg_wal日志

    一.简介 读取MySQL的binlog 并将其解析为可读的日志是一件简单的事情,mysqlbinlog 命令就可以将bin日志解析, 那postgresql是否可以将pg_wal 中的日志进行解析,并 ...

  3. pat乙级 1021个位数统计

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> ...

  4. [WPF]MVVM的数据绑定

    啥是MVVM? 我理解的MVVM是Model(数据),View(界面),ViewModel(数据与界面之间的桥梁)的缩写,是一种编程模式.前期需要多花一些时间去编辑绑定,在后期维护方便.只需要关注数据 ...

  5. mybatis动态标签——trim

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "- ...

  6. Redis入门级简单安装使用

      最近突然就想学一下Redis,于是就各种找教程,前两天实际操作了一下,也不是想象中的很难 但是今天想写一个使用Redis的demo,突然就不会使用Redis了,在网上也是查找了半天,还是想起来了点 ...

  7. 基于GPU 显卡在k8s 集群上实现hpa 功能

    前言 Kubernetes 支持HPA模块进行容器伸缩,默认支持CPU和内存等指标.原生的HPA基于Heapster,不支持GPU指标的伸缩,但是支持通过CustomMetrics的方式进行HPA指标 ...

  8. linux 多级时间轮应用场景

    参考链接: https://www.163.com/dy/article/GMGUO9UV05421U51.html

  9. nodejs web学习

    命令行 和python一样,出奇的简单 npm i serve -g serve -s softwares 如果当前目录,就直接 serve express /** * 服务器代码 * 启动方式: * ...

  10. javaweb项目启动脚本

    #存放的位置www_path=/home/project/api #编译好的jar名称jar_name=springboot1.0.jar #获取运行编译好的进程ID,便于我们在重新部署项目的时候先杀 ...