Spring Boot + Vue 项目中的跨域配置与优化

news/2025/3/31 18:23:36/文章来源:https://www.cnblogs.com/java-note/p/18798974

一、跨域问题概述

(一)什么是跨域问题

  1. 定义
  • 跨域问题源于浏览器的 同源策略(Same-Origin Policy)。同源策略是一种重要的安全机制,它限制了来自不同源(Origin)的文档或脚本之间的交互能力。具体来说,如果一个网页的资源(如HTML、JavaScript、CSS等)来自一个源(例如http://example.com),那么它只能与来自同一源的资源进行交互。如果尝试访问来自另一个源(例如http://another-example.com)的资源,就会触发跨域问题。
  • 的定义包括:协议(httphttps)、域名(example.comsub.example.com)、端口号(808080)。只要这三者中有一个不同,就被视为不同源。
  1. 背景
  • 在现代Web开发中,前后端分离架构非常常见。前端项目通常运行在本地开发服务器(如http://localhost:8080),而后端服务可能运行在另一个端口(如http://localhost:8789)或完全不同的域名上。在这种情况下,前端代码尝试向后端服务发送请求时,就会遇到跨域问题。
  1. 示例
  • 假设前端项目运行在http://localhost:8080,后端服务运行在http://localhost:8789。当前端代码中使用axios或其他HTTP客户端向http://localhost:8789/api/data发送请求时,浏览器会阻止该请求,并在控制台中报错:

    Access to XMLHttpRequest at 'http://localhost:8789/api/data' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
    
  • 这是因为后端服务没有明确告诉浏览器它允许来自http://localhost:8080的请求。

(二)跨域问题的表现

  1. 常见的错误信息
  • Access to XMLHttpRequest at 'http://example.com/api/data' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.:表示后端没有返回Access-Control-Allow-Origin头,浏览器拒绝了请求。
  • Access to fetch at 'http://example.com/api/data' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.:表示预检请求(OPTIONS请求)失败。
  • Access to XMLHttpRequest at 'http://example.com/api/data' from origin 'http://localhost:8080' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values 'http://localhost:8080, *', but only one is allowed.:表示Access-Control-Allow-Origin头的值不合法,不能同时包含多个值。
  1. 影响
  • 跨域问题会导致前端无法正常获取后端数据,影响页面的渲染和功能实现。
  • 如果不解决跨域问题,前端项目在开发阶段和生产环境中都无法正常工作。

(三)跨域问题的解决思路

  1. 后端解决
  • 后端可以通过设置响应头,允许特定的前端域名或所有域名访问其资源。这是最常用和推荐的解决方案,因为它将跨域控制逻辑集中在后端,前端不需要做额外的处理。
  1. 前端解决
  • 前端可以通过配置代理,将请求转发到后端服务。这种方法主要适用于开发阶段,生产环境中通常不建议使用前端代理。
  1. 其他解决方案
  • JSONP(仅支持GET请求):通过动态创建<script>标签来绕过跨域限制,但这种方法存在安全风险,且功能有限。
  • WebSocket:WebSocket协议不受同源策略限制,因此可以用于跨域通信,但仅适用于实时通信场景。

二、后端(Spring Boot)跨域配置

(一)使用 @CrossOrigin 注解

  1. 基本用法
  • @CrossOrigin注解是Spring MVC提供的一个简单方式,用于在Controller类或方法上声明允许跨域请求。

  • 示例代码:

    @RestController
    public class BasicController {@RequestMapping("/user")@CrossOrigin("http://localhost:5173")public User user() {User user = new User();user.setName("张三");user.setAge(666);return user;}
    }
    
  • 在这个例子中,@CrossOrigin("http://localhost:5173")表示只允许来自http://localhost:5173的请求访问/user接口。

  1. 高级配置
  • @CrossOrigin注解支持多种配置选项:

    • origins:允许访问的前端域名,可以是一个字符串或字符串数组。如果设置为*,表示允许所有域名访问。
    • methods:允许的HTTP方法,如GETPOSTPUTDELETE等。如果未指定,则默认允许所有方法。
    • allowedHeaders:允许的请求头字段。
    • exposedHeaders:允许客户端访问的响应头字段。
    • allowCredentials:是否允许发送Cookie。如果设置为true,则origins不能为*
    • maxAge:预检请求(OPTIONS请求)的缓存时间,单位为秒。
  • 示例代码:

    @RestController
    public class BasicController {@RequestMapping("/user")@CrossOrigin(origins = "http://localhost:5173", methods = {RequestMethod.GET, RequestMethod.POST}, allowedHeaders = "X-Requested-With", allowCredentials = "true", maxAge = 3600)public User user() {User user = new User();user.setName("张三");user.setAge(666);return user;}
    }
    

(二)全局CORS配置

  1. 通过实现 WebMvcConfigurer 接口
  • 如果希望对整个应用的跨域行为进行统一配置,可以实现WebMvcConfigurer接口并重写addCorsMappings方法。

  • 示例代码:

    @Configuration
    public class CorsConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**") // 配置允许跨域的路径,`/**`表示所有路径.allowedOrigins("http://localhost:5173") // 允许的前端域名.allowCredentials(true) // 是否允许发送Cookie.maxAge(3600) // 预检请求的缓存时间,单位为秒.allowedHeaders("*") // 允许的请求头字段.allowedMethods("GET", "POST", "PUT", "DELETE"); // 允许的HTTP方法}
    }
    
  • 这种方式的优点是配置集中,便于管理和维护。缺点是不够灵活,无法针对特定接口进行特殊配置。

  1. 配置项说明
  • addMapping:指定需要跨域的路径。
  • allowedOrigins:允许访问的前端域名,可以是一个字符串或字符串数组。如果设置为*,表示允许所有域名访问。
  • allowCredentials:是否允许发送Cookie。如果设置为true,则allowedOrigins不能为*
  • maxAge:预检请求(OPTIONS请求)的缓存时间,单位为秒。
  • allowedHeaders:允许的请求头字段。
  • allowedMethods:允许的HTTP方法。

(三)配置 CorsFilter

  1. 创建 CorsFilter
  • 如果需要更细粒度的跨域控制,可以创建一个CorsFilter。通过CorsConfigurationUrlBasedCorsConfigurationSource来配置CORS,并返回CorsFilter对象。

  • 示例代码:

    @Configuration
    public class CorsFilterConfig {@Beanpublic CorsFilter corsFilter() {UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();CorsConfiguration config = new CorsConfiguration();config.setAllowCredentials(true); // 是否允许发送Cookieconfig.addAllowedOrigin("http://localhost:5173"); // 允许的前端域名config.addAllowedHeader("*"); // 允许的请求头字段config.addAllowedMethod("*"); // 允许的HTTP方法source.registerCorsConfiguration("/**", config); // 配置允许跨域的路径return new CorsFilter(source);}
    }
    
  1. 配置项说明
  • CorsConfiguration:用于配置CORS的具体规则。
  • UrlBasedCorsConfigurationSource:用于将CORS配置与URL路径关联起来。
  • CorsFilter:最终生成的过滤器,会在请求到达Controller之前检查跨域规则。

(四)手动设置响应头

  1. 在Controller中设置
  • 在Controller方法中,可以通过HttpServletResponse手动添加Access-Control-Allow-Origin响应头来允许特定的前端域名访问。

  • 示例代码:

    @RestController
    public class BasicController {@RequestMapping("/index")public String index(HttpServletResponse response) {response.addHeader("Access-Control-Allow-Origin", "http://localhost:5173");response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");response.addHeader("Access-Control-Allow-Headers", "X-Requested-With");response.addHeader("Access-Control-Allow-Credentials", "true");return "index";}
    }
    
  1. 适用场景
  • 这种方式适用于简单的场景,或者需要在特定方法中动态设置跨域规则的情况。但不推荐在大型项目中广泛使用,因为它会增加代码的复杂性和维护成本。

三、前端(Vue)跨域配置

(一)配置代理

  1. 原理
  • 在开发阶段,Vue CLI提供了一个代理功能,可以将前端请求转发到后端服务。这样,浏览器会认为请求是同源的,从而避免跨域问题。
  • 代理的原理是通过Node.js的http-proxy-middleware中间件实现的。当前端发送请求到代理服务器时,代理服务器会将请求转发到目标后端服务,并将响应返回给前端。
  1. 配置方法
  • 在Vue项目的vue.config.js文件中配置代理:

    module.exports = {devServer: {proxy: {'/api': {target: 'http://localhost:8789', // 后端服务的地址changeOrigin: true, // 是否允许跨域pathRewrite: {'^/api': '' // 重写路径,去掉`/api`前缀}}}}
    };
    
  • 在这个例子中,当前端发送请求到http://localhost:8080/api/data时,Vue CLI的开发服务器会将请求转发到http://localhost:8789/data

  1. 适用场景
  • 代理主要适用于开发阶段,用于解决开发环境下的跨域问题。在生产环境中,通常不建议使用前端代理,而是通过后端配置CORS或使用其他方式解决跨域问题。

(二)修改前端请求路径

  1. 路径调整
  • 配置代理后,前端代码中的请求路径需要调整为代理路径。例如,如果代理配置为/api,则请求路径应从http://localhost:8789/data改为/api/data

  • 示例代码:

    axios.get('/api/data').then(response => {console.log(response.data);}).catch(error => {console.error(error);});
    
  1. 注意事项
  • 确保请求路径与代理配置一致,否则代理不会生效。
  • 在生产环境中,前端代码中的请求路径应直接指向后端服务的实际地址,而不是代理路径。

四、测试与验证

(一)启动服务

  1. 后端服务
  • 启动Spring Boot项目,确保后端服务正常运行。可以通过访问后端接口(如http://localhost:8789/api/data)来验证后端是否正常响应。
  1. 前端服务
  • 启动Vue项目,运行在本地开发服务器(如http://localhost:8080)。可以通过访问前端页面来验证前端是否正常加载。

(二)发起请求

  1. 测试跨域请求
  • 在前端页面中,使用axios或其他HTTP客户端向后端接口发送请求:

    axios.get('/api/data').then(response => {console.log(response.data);}).catch(error => {console.error(error);});
    
  • 观察浏览器控制台的输出:

    • 如果配置正确,前端应能成功获取后端数据,并在控制台中打印出响应内容。
    • 如果配置错误,浏览器会报错,显示跨域问题的相关错误信息。
  1. 检查响应头
  • 使用开发者工具(如Chrome DevTools)查看响应头,确认后端是否正确返回了CORS相关的头字段,如Access-Control-Allow-OriginAccess-Control-Allow-Methods等。

(三)验证不同场景

  1. 测试不同HTTP方法
  • 分别测试GETPOSTPUTDELETE等HTTP方法,确保后端的跨域配置支持所有需要的方法。
  1. 测试带Cookie的请求
  • 如果需要在请求中携带Cookie(如登录认证),确保allowCredentials配置为true,并且allowedOrigins不能为*

  • 示例代码:

    axios.get('/api/data', { withCredentials: true }).then(response => {console.log(response.data);}).catch(error => {console.error(error);});
    
  1. 测试预检请求(OPTIONS)
  • 浏览器在发送某些复杂请求(如带有自定义头的POST请求)之前,会先发送一个OPTIONS预检请求,以确认后端是否允许该请求。确保后端的跨域配置能够正确处理OPTIONS请求。

五、拓展学习

(一)了解跨域的其他解决方案

  1. JSONP
  • 原理:JSONP(JSON with Padding)是一种古老的跨域解决方案。它的原理是利用<script>标签的src属性不受同源策略限制的特点,通过动态创建<script>标签来加载一个外部的JavaScript文件,并在加载完成后执行回调函数。

  • 示例代码

    function handleResponse(data) {console.log(data);
    }const script = document.createElement('script');
    script.src = 'http://example.com/data?callback=handleResponse';
    document.head.appendChild(script);
    
  • 限制:JSONP仅支持GET请求,且存在安全风险(如XSS攻击),因此不推荐在现代项目中使用。

  1. WebSocket
  • 原理:WebSocket是一种基于TCP的协议,用于实现客户端和服务器之间的双向通信。WebSocket协议不受同源策略限制,因此可以用于跨域通信。

  • 适用场景:适用于需要实时通信的场景,如在线聊天、实时数据推送等。

  • 示例代码

    const socket = new WebSocket('ws://example.com/socket');
    socket.onmessage = function(event) {console.log(event.data);
    };
    socket.send('Hello, server!');
    

(二)学习跨域问题的原理

  1. 同源策略
  • 定义:同源策略是一种重要的网络安全机制,用于限制来自不同源的文档或脚本之间的交互能力。它防止恶意网站窃取用户的敏感信息,如Cookie、本地存储等。
  • 原理:浏览器会检查请求的源(协议、域名、端口)是否与当前页面的源一致。如果不一致,则会阻止某些操作,如读取DOM、发送AJAX请求等。
  1. CORS机制
  • 定义:CORS(Cross-Origin Resource Sharing,跨域资源共享)是一种基于HTTP头的机制,允许服务器明确告诉浏览器哪些外部域名可以访问其资源。
  • 工作原理
    • 当浏览器检测到跨域请求时,会先发送一个OPTIONS预检请求到目标服务器,询问服务器是否允许该请求。
    • 服务器在响应中返回CORS相关的头字段,如Access-Control-Allow-OriginAccess-Control-Allow-Methods等。
    • 浏览器根据这些头字段决定是否允许请求继续进行。
  • 关键头字段
    • Access-Control-Allow-Origin:指定允许访问的前端域名,或*表示允许所有域名。
    • Access-Control-Allow-Methods:指定允许的HTTP方法。
    • Access-Control-Allow-Headers:指定允许的请求头字段。
    • Access-Control-Allow-Credentials:是否允许发送Cookie。
    • Access-Control-Max-Age:预检请求的缓存时间,单位为秒。

(三)实践复杂场景下的跨域配置

  1. 使用Spring Security的跨域配置
  • 如果后端项目使用了Spring Security进行安全控制,跨域配置可能会更加复杂。因为Spring Security会拦截请求并进行认证和授权,可能会与CORS配置冲突。
  • 解决方案
    • 在Spring Security的配置中,允许跨域请求的路径。例如:

      @Configuration
      @EnableWebSecurity
      public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.cors().and().csrf().disable();http.authorizeRequests().antMatchers("/api/**").permitAll().anyRequest().authenticated();}
      }
      
    • 确保CORS配置在Spring Security之前生效。可以通过调整配置类的加载顺序或使用@Order注解来实现。

  1. 跨域与Cookie管理
  • 如果需要在跨域请求中携带Cookie(如登录认证),需要特别注意以下几点:
    • 后端的CORS配置中,allowCredentials必须设置为true,并且allowedOrigins不能为*
    • 前端在发送请求时,需要设置withCredentials: true
    • 确保Cookie的SameSite属性设置为None,并且Secure属性设置为true(如果使用HTTPS)。
  1. 跨域与GraphQL
  • 如果后端使用了GraphQL,跨域配置可能会有所不同。GraphQL通常使用POST请求发送查询,因此需要确保CORS配置允许POST方法。

  • 示例代码:

    @Configuration
    public class CorsConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/graphql").allowedOrigins("http://localhost:5173").allowCredentials(true).allowedMethods("POST").allowedHeaders("*");}
    }
    

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Bitcoin部署到openEuler RISC-V

Bitcoin项目源码是用C++写的,我对C++以及它的编译工具又比较熟悉,这次我尝试了在openEuler RISC-V 24.09上面部署Bitcoin。网上编译Bitcoin源码的很多都是以前旧版的,旧版编译是用automake之类的工具,但是在最新版只需要用cmake就行,两者的部署方式不相同,我分别记录一下…

NVIDIA安装程序无法继续

原因 在更新驱动时,手贱,下驱动一半关闭了下载流程。导致下载失败,而且进入不了Geforece 解决方法:官网下载最新版驱动,再尝试。 如果不行,检查Windows更新,更新至最新版本 重启后如果不可行,再关闭杀毒软件,关闭防火墙,再尝试,重启再尝试。 如果还是不行,使用卸载…

锚定碳中和,三重角色重构,运营商的第四次跃迁

「 作为能源消耗大户,运营商在面对碳中和的级终命题时需要转变发展思路、转变角色定位。」5G+AI倒逼运营商基础设施建设大规模提速,运营商要更好的生存发展必须要降本提效,碳中和的大目标则要求运营商在快速发展的同时还要破解能源消耗指数级增长的魔咒——这似乎是一个不可…

SpringBoot整合RabbitMQ--Fanout模式

使用springBoot整合rabbitMQ需要事先导入相关依赖:<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>org.springframework.bo…

查看网站支持的tls版本

f12 打开chrome 开发面板本文由 trykle 发布联系方式:QQ 294986636本文地址:https://www.cnblogs.com/trykle/p/18798939

解析PromQL并修改添加Label

最近做的项目中用到了Prometheus做预警服务,其中Prometheus使用promql语言来查询。项目中用户通过UI或者自己手动输入PromQL时候是缺少一些系统参数的,所以需要在用户输入完成以后同步到Prometheus时候将这部分缺失的信息给添加回去,这里就需要修改用户写的PromQL了。 实现思…

学习安装配置vue

1.先将nodejs下载2.在我们的安装目录下,创建名为node_cache和node_global的两个文件夹 3.打开cmd窗口,执行如下命令,将npm的全局模块目录和缓存目录配置到刚才创建的那两个目录。 npm config set prefix “D:\soft2024.7.6\nodejs\node_global” npm config set cache “D:\…

K8s Ingress, 你这个老6

Ingress 这个老6,结合nodeport和ClusterIp两种服务类型,你在引流这一块玩的花啊。 入口一夫当关,对内如鱼得水。本文是有态度马甲的第185篇原创。 本文记录了k8s中核心对象Ingress的产生背景和实现机制。 我们都知道k8s Service是一种将Pods通过网络暴露出来的抽象,每个服务…

C# .NET core 中处理图像,SkiaSharp,ImageSharp,NetVips,Magick.net多维度对比

2025年有哪些图像处理库,我们可以在项目中使用哪些库?本文列出了最流行的现有库。 .NET Core图片处理库SkiaSharp(https://github.com/mono/SkiaSharp) Magick.net(https://github.com/dlemstra/Magick.NET) ImageSharp(https://github.com/SixLabors/ImageSharp) NetV…

20243317 实验二《Python程序设计》实验报告

课程:《Python程序设计》 班级: 2433 姓名: 邓雅文 学号:20243317 实验教师:王志强老师 实验日期:2025年3月26日 必修/选修: 公选课 一、实验内容 1、掌握python中函数定义与调用相关知识点 大致框架与C语言相同,同样有实参,形参,可能有返回值,形式如下: def 函数名…

MEBCY-v2

MERCY-v2 信息收集 查找目标主机ip ┌──(root㉿kali)-[~] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:84:b2:cc, IPv4: 192.168.158.143 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.158.1 00:50:56:c…

人群密度分析预警摄像机

人群密度分析预警摄像机是可以实时地统计出一个指定区域内的总人数。当所监视区域的人员数量达到设定的阀值时摄像机输出报警信号。可设置人数阈值和时间阈值。用于设置触发进入区域内的人数值,达到该设定的阈值则摄像机输出报警信号。人数阈值可以手动设置,系统默认值为5人,…