砍材农夫砍材农夫
  • 微信记账小程序
  • java
  • redis
  • mysql
  • 场景类
  • 框架类
  • vuepress搭建
  • hexo搭建
  • 云图
  • llm wiki

    • 基于karpathy
    • gradle
  • 常用工具

    • git
    • gradle
    • Zadig
    • it-tools
    • 开源推荐
    • curl
  • 大前端

    • 环境配置
    • 微信生态
    • 正则
    • 全栈技能
  • java圈

    • java基础
    • jdk体系
    • jvm
    • spring框架
    • 分库分表
    • zookeeper
  • python技能

    • python编程
    • python数据
  • 算法

    • 算法
  • 网关

    • spring_cloud_gateway
    • openresty
  • 高可用

    • 秒杀
    • 分布式
    • 缓存一致
  • MQ

    • MQ
    • rabbitMQ
    • rocketMQ
    • kafka
  • 其它

    • 设计模式
    • 领域驱动(ddd)
  • 关系型数据库

    • mysql5.0
    • mysql8.0
  • 非关系型数据库

    • redis
    • mongoDB
  • 分布式/其他

    • ShardingSphere
    • 区块链
  • 向量数据库

    • M3E
    • OPEN AI
  • Jmeter
  • fiddler
  • wireshark
  • AI入门
  • AI大模型
  • AI插件
  • AI集成框架
  • 相关算法
  • AI训练师
  • 量化交易
  • AIoT
  • gitee
  • github
  • infoq
  • osc
  • 砍材工具
  • 关于
  • 相关运营
  • devops
  • 元宇宙
  • 区块链
  • 物联网
  • webrtc
  • web3.0
  • gitee
  • github
  • infoq
  • osc
  • 砍材工具
  • 关于
  • 中考
  • 投资
  • 保险
  • 思
  • 微信记账小程序
  • java
  • redis
  • mysql
  • 场景类
  • 框架类
  • vuepress搭建
  • hexo搭建
  • 云图
  • llm wiki

    • 基于karpathy
    • gradle
  • 常用工具

    • git
    • gradle
    • Zadig
    • it-tools
    • 开源推荐
    • curl
  • 大前端

    • 环境配置
    • 微信生态
    • 正则
    • 全栈技能
  • java圈

    • java基础
    • jdk体系
    • jvm
    • spring框架
    • 分库分表
    • zookeeper
  • python技能

    • python编程
    • python数据
  • 算法

    • 算法
  • 网关

    • spring_cloud_gateway
    • openresty
  • 高可用

    • 秒杀
    • 分布式
    • 缓存一致
  • MQ

    • MQ
    • rabbitMQ
    • rocketMQ
    • kafka
  • 其它

    • 设计模式
    • 领域驱动(ddd)
  • 关系型数据库

    • mysql5.0
    • mysql8.0
  • 非关系型数据库

    • redis
    • mongoDB
  • 分布式/其他

    • ShardingSphere
    • 区块链
  • 向量数据库

    • M3E
    • OPEN AI
  • Jmeter
  • fiddler
  • wireshark
  • AI入门
  • AI大模型
  • AI插件
  • AI集成框架
  • 相关算法
  • AI训练师
  • 量化交易
  • AIoT
  • gitee
  • github
  • infoq
  • osc
  • 砍材工具
  • 关于
  • 相关运营
  • devops
  • 元宇宙
  • 区块链
  • 物联网
  • webrtc
  • web3.0
  • gitee
  • github
  • infoq
  • osc
  • 砍材工具
  • 关于
  • 中考
  • 投资
  • 保险
  • 思
  • spring_boot

    • SpEL(表达式)

      • 概念
      • 常用命令
      • nginx安装和部署
  • spring_cloud

    • 入门

      • SpEL(表达式)

        • 概念
        • 常用命令
        • nginx安装和部署
  • spring_core

    • SpEL(表达式)

      • 概念
      • 常用命令
      • nginx安装和部署
    • spring event

      • spring event入门
      • spring event高性能
      • spring event顺序和条件
      • spring event泛化
    • spring web

      • spring web拦截器、过滤器、aop
      • spring web拦截器、过滤器、aop顺序
      • spring web跨域问题
      • spring web集成spring_cloud跨域
  • spring_tools

    • 入门

      • SpEL(表达式)

        • 概念
        • 常用命令
        • nginx安装和部署
  • spring|spring web|跨域问题
    • 跨域
      • 同源的判断标准:三者必须全部相同
      • CORS
      • 后端返回特殊响应头给浏览器
      • OPTIONS预检请求
    • 源码
    • pom依赖
    • 部分代码
      • 全局
      • 指定接口
    • 验证结果

spring|spring web|跨域问题

基于spring-boot 4.0.x

跨域

浏览器的安全规则:同源策略 (Same‑Origin Policy),防止 CSRF 安全攻击

同源的判断标准:三者必须全部相同

  • 协议 + 域名(IP) + 端口,有任意一个不一样 → 不同源 = 跨域
前端页面地址后端接口地址是否跨域原因
http://localhost:5173http://localhost:8080✅ 跨域端口不一样
http://a.comhttps://a.com✅ 跨域协议 http/https 不一样
http://a.comhttp://b.com✅ 跨域域名不一样
http://127.0.0.1:5173http://localhost:8080✅ 跨域IP / 域名不同
http://a.com:8080/apihttp://a.com:8080/user❌ 不跨域协议、域名、端口全部一致,只是路径不同

CORS

  • CORS = Cross‑Origin Resource Sharing 跨域资源共享
  • 就是后端告诉浏览器:这个来源的前端是合法的,请放行,允许 JS 读取返回结果

后端返回特殊响应头给浏览器

Access‑Control‑Allow‑Origin: http://localhost:5173   #允许哪个前端来源
Access‑Control‑Allow‑Credentials: true              #是否允许cookie/token凭证
Access‑Control‑Allow‑Methods: GET,POST,PUT...       #允许哪些请求方法

OPTIONS预检请求

当前端是复杂请求(带 cookie、自定义 header,如 token),浏览器不会直接发 POST,先发一次OPTIONS请求询问后端:“允许这个跨域请求吗?”

源码

https://gitee.com/jysemel-spring/spring-boot/tree/master/action/action-web-sample/action-web-sample-cors

pom依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webmvc</artifactId>
    </dependency>
    <!-- AOP 切面依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aspectj</artifactId>
    </dependency>
</dependencies>

部分代码

全局

package com.jysemel.spring.boot.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/global")
public class GlobalController {



    @GetMapping("/test")
    public String test() {
        System.out.println("【业务代码】Controller业务逻辑执行");
        return "success";
    }
}
package com.jysemel.spring.boot.interceptor;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {



    @Override
    public void addCorsMappings(CorsRegistry registry) {
        //指定  global 路径前缀 全局放开
        registry.addMapping("/global/**")
                .allowedOriginPatterns("*")
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowedHeaders("*")
                .allowCredentials(true)
                .maxAge(3600);
    }
}

指定接口

package com.jysemel.spring.boot.controller;

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/cross")
@CrossOrigin(
        originPatterns = "*",
        allowCredentials = "true",
        allowedHeaders = "*",
        methods = {RequestMethod.GET, RequestMethod.POST},
        maxAge = 3600
)
public class CrossController {

    @GetMapping("/test")
    public String test() {
        System.out.println("【业务代码】/cross/test 业务逻辑执行");
        return "success";
    }

    @GetMapping("/options-demo")
    public String optionsDemoGet() {
        System.out.println("【业务代码】/cross/options‑demo GET业务执行");
        return "options‑demo‑get‑ok";
    }

    // Spring7强制:该path必须存在OPTIONS映射,@CrossOrigin注解才会对OPTIONS生效
    @RequestMapping(value = "/options-demo", method = RequestMethod.OPTIONS)
    public void preflightOptions() {
        //空实现,仅占位,不会执行业务
    }
}  

验证结果

img

img

img

最近更新: 2026/9/18 16:29
Contributors: kcnf
Prev
spring web拦截器、过滤器、aop顺序
Next
spring web集成spring_cloud跨域