盘点 Spring Boot 解决跨域请求的几种办法

news/2024/10/3 10:35:02

熟悉 web 系统开发的同学,对下面这样的错误应该不会太陌生。

之所以会出现这个错误,是因为浏览器出于安全的考虑,采用同源策略的控制,防止当前站点恶意攻击 web 服务器盗取数据。

01、什么是跨域请求

同源策略,简单的说就是当浏览器访问 web 服务器资源时,只有源相同才能正常进行通信,即协议、域名、端口号都完全一致,否则就属于跨域请求。当发起跨域请求时,服务端是能收到请求并正常返回结果的,只是结果被浏览器拦截了。

像上文中,浏览器访问的站点是http://127.0.0.1:8848/,而站点内发起的接口请求源是http://localhost:8080,因为不同源,所以报跨域请求异常。

由此可见,想要实现接口请求的正常访问,浏览器的访问站点源和接口请求源,必须得一致。

事实上,在现在流行的前后端分离的开发模式下,很难做到请求源高度一致,那怎么办呢?

答案肯定是有办法啦!

虽然浏览器出于安全的考虑,默认采用同源策略控制,以便减少服务器被恶意攻击的机会,但是开发者可以通过CORS协议在浏览器内实现站内跨域请求访问。

实现很简单,通过在 web 服务器中增加一个特殊的Header响应属性来告诉浏览器解除跨域的限制,如果浏览器支持CORS并且判断允许通过的话,此时发起的跨域请求就可以正常展示了。

常用的 Header 响应属性如下:

Header 属性 作用
Access-Control-Allow-Origin 设置允许跨域请求的请求源,比如www.xxx.com
Access-Control-Max-Age 设置预检请求的结果能被缓存的时间,单位秒,比如1800
Access-Control-Allow-Methods 设置允许跨域请求的方法,比如GET, POST, OPTIONS, PUT, DELETE
Access-Control-Allow-Headers 设置允许跨域请求的头部信息,比如Content-Type, Accept
Access-Control-Allow-Credentials 设置是否允许携带凭证(比如cookies),参数值只能是true或者不设置

带着以上的信息,我们就一起来了解一下如何在 Spring Boot 应用中实现跨域访问。

02、解决方案

2.1、方法一:采用过滤器的方式全局配置

采用过滤器的方式来实现所有接口支持跨域请求,是一种比较通用的做法,也是 Java web 项目中常用的方法,实现过程如下!

首先,创建一个实现自Filter接口的过滤器,示例如下:

public class CrossFilter implements Filter {/*** 允许跨域的白名单域名*/private final static Set<String> ALLOW_DOMAINS = new HashSet<>();static {ALLOW_DOMAINS.add("http://127.0.0.1:8848");}@Overridepublic void init(FilterConfig config) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest)servletRequest;HttpServletResponse response = (HttpServletResponse)servletResponse;// 获取客户端原始请求域String origin = request.getHeader("Origin");String originDomain = removeHttp(origin);if(ALLOW_DOMAINS.contains(originDomain)){// 在响应对象中,添加CROS协议相关的header属性response.setHeader("Access-Control-Allow-Origin", origin);response.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,DELETE,HEAD,PUT,PATCH");response.setHeader("Access-Control-Max-Age", "3600");response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,Authorization,authorization");response.setHeader("Access-Control-Allow-Credentials","true");}//继续往下传递filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {}/*** 移除http协议头部* @param url* @return*/public static String removeHttp(String url){return url.replace("http://", "").replace("https://", "");}}

接着,将其注册到Servlet容器中,示例如下:

@Configuration
public class FilterConfig {/*** 添加CrossFilter过滤器* @return*/@Beanpublic FilterRegistrationBean crossFilterBean() {FilterRegistrationBean registration = new FilterRegistrationBean();registration.setName("crossFilter"); // 指定过滤器名称registration.setFilter(new CrossFilter()); // 指定过滤器实现类registration.setUrlPatterns(Collections.singleton("/*"));// 指定拦截路径registration.setOrder(1);// 指定顺序return registration;}
}

最后,启动服务后,再到浏览器中发起跨域请求,看看效果如下。

从结果上看,浏览器成功进行了跨域请求,并展示了服务器返回的结果。

2.2、方法二:通过全局配置类实现跨域访问

在 Spring Boot 应用,除了采用过滤器的方式实现跨域访问外,我们还可以通过全局配置类实现跨域访问。

实现方法也非常简单,只需要重写WebMvcConfigurer接口中的addCorsMappings方法即可,示例如下:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOrigins("*").allowedMethods("GET", "POST", "PUT", "DELETE").maxAge(3600).allowedHeaders("Origin", "Accept", "Content-Type", "Authorization").allowCredentials(true);}
}

其中allowedOrigins("*")表示对所有请求都允许跨域访问。

2.3、方法三:通过CrossOrigin注解实现跨域访问

某些场景,如果不希望所有的接口都能跨域访问,只想在部分接口上放开跨域访问。此时,可以通过 Spring Boot 提供的@CrossOrigin注解,在对应的方法上加上该注解,即可实现跨域访问。

示例如下:

@RestController
public class UserController {@Autowiredprivate UserService userService;@CrossOrigin@PostMapping(value = "/queryAll")public List<User> queryAll(){List<User> result = userService.queryAll();return result;}
}

如果使用在controller类上,表示当前类下的所有接口方法都允许跨域访问。

同时,@CrossOrigin注解也支持设置更小的粒度,示例如下:

@CrossOrigin(origins = "http://domain.com", maxAge = 1800)

更多的属性行为,内容如下:

  • origins: 允许的源列表,多个源可以使用逗号分隔
  • methods: 允许的 HTTP 方法列表
  • allowedHeaders: 允许的请求头列表,默认情况下,允许所有请求头
  • allowCredentials:设置是否允许携带凭证
  • maxAge: 预检请求的缓存时间(以秒为单位)

03、小结

最后总结一下,在 Spring Boot 服务中可以通过过滤器或者配置类实现全局跨域访问,也可以通过@CrossOrigin注解实现局部跨域访问。

跨域访问的配置,更适合在开发环境中方便前后端进行联调对接。为了安全起见,在上生产的时候,建议将其关闭掉或者做限制。

此外,想要获取项目源代码的小伙伴,可以点击:跨域请求,即可获取取项目的源代码。

04、参考

1.https://cloud.tencent.com/developer/article/1655583

2.https://cloud.tencent.com/developer/article/1924258

写到最后

不会有人刷到这里还想白嫖吧?点赞对我真的非常重要!在线求赞。加个关注我会非常感激!

本文已整理到技术笔记中,此外,笔记内容还涵盖 Spring、Spring Boot/Cloud、Dubbo、JVM、集合、多线程、JPA、MyBatis、MySQL、微服务等技术栈。

需要的小伙伴可以点击 技术笔记 获取!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/44624.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

基于正点原子ZYNQ7020的RTSP摄像头视频流获取

记录如何修改,编译定制化petalinux镜像,实现PS端和PL端互通硬件描述 硬件需求ZYNQ7020 系列 LCD 显示屏 800*600rtsp 网口摄像头接线方式USB_UART 通过 type-c 线连接电脑,电脑需要安装 CH340 的串口驱动 ps 端网口和摄像头的网口连接 开发板和摄像头的电源线连接 LCD 显示屏的…

移动平台开发综合实践 安卓android大作业-雷net在线对战

转自我的安卓课程作业 图片应该是没了,懒得搞了目录移动平台开发综合实践 大作业-雷net在线对战一、实验目的二、实验环境三、实验内容与实验要求3.1实验内容:雷net在线对战3.1.1棋盘3.1.2棋子3.1.3终端卡3.2原理分析3.3具体实验要求四、实验过程与分析4.1实验记录4.1.1 Sock…

解析Html Canvas的卓越性能与高效渲染策略

一、什么是Canvas 想必学习前端的同学们对Canvas 都不陌生,它是 HTML5 新增的“画布”元素,可以使用JavaScript来绘制图形。 Canvas元素是在HTML5中新增的标签用于在网页实时生成图像,并且可以操作图像内容,基本上它是一个可以用JavaScript操作的位图(bitmap)。Canvas 由…

怎么控制多个存储设备的访问权限?数据安全存储方案来了

数据安全存储是指将数据以安全的方式存储在存储系统中,以确保数据的机密性、完整性和可用性。要控制数据安全存储的权限以保障安全,可以采取以下措施:访问控制列表(ACLs):使用ACLs来定义对存储数据的访问权限。ACLs允许你为每个文件或目录指定哪些用户或组有权访问它们,…

GPT-4o 只是对话式 Al 的冰山一角,背后隐藏了哪些新机会?(内含福利) | 编码人声

「编码人声」是由「RTE开发者社区」策划的一档播客节目,关注行业发展变革、开发者职涯发展、技术突破以及创业创新,由开发者来分享开发者眼中的工作与生活。 听友福利 欢迎在小宇宙播客评论区留言,分享你对 GPT-4o 的看法,或者对最有潜力的对话式 AI 场景的预测。我们将抽出…

一个开源的快速准确地将 PDF 转换为 markdown工具

大家好,今天给大家分享的是一个开源的快速准确地将 PDF 转换为 markdown工具。 Marker是一款功能强大的PDF转换工具,它能够将PDF文件快速、准确地转换为Markdown格式。这款工具特别适合处理书籍和科学论文,支持所有语言的转换,并且能够去除页眉、页脚等干扰元素,格式化表格…

简单聊聊Unicode

接下来我们简单讲讲,Unicode 的原理,例如,Unicode 的设计思路,Unicode 和 UTF 的关系等。接下来我们简单讲讲,Unicode 的原理,例如,Unicode 的设计思路,Unicode 和 UTF 的关系等。 ‍ 简单的字符编码模型 一个字符,在计算机中如何存储,是涉及到很多部分的。例如,一个…

有手就行!10分钟上手实现文生图!

Fooocus 一款基于 Gradio 实现的图像生成软件,提供高质量的文本生成图像功能,完全离线、开源、免费。大家好,我是 Java陈序员。 今天,给大家介绍一个文生图工具,无需繁杂的配置,一键安装启动,十分钟就能实现文生图!关注微信公众号:【Java陈序员】,获取开源项目分享、…