SpringBoot/SSM体系下跨域解决方案

本文提供SpringBoot及SSM框架下的跨域处理方案。SpringBoot通过WebConfigurer配置实现,SSM则需自定义过滤器并配置于web.xml中。两种方案均支持自定义属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文总结SpringBoot或者SSM体系下跨域后端处理方案。

【1】SpringBoot

直接在WebConfigurer配置即可,具体属性/值可以根据需要自定义

//跨域配置
@Override
public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**").
            allowedOrigins("*"). //允许跨域的域名,可以用*表示允许任何域名使用
            allowedMethods("*"). //允许任何方法(post、get等)
            // allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS"). //允许任何方法(post、get等)
            allowedHeaders("*"). //允许任何请求头
            allowCredentials(true). //带上cookie信息
            exposedHeaders(HttpHeaders.SET_COOKIE)
            .maxAge(3600L);
    //maxAge(3600)表明在3600秒内,不需要再发送预检验请求,可以缓存该结果
}

或者如下所示:

@Bean
public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    // 设置允许跨域请求的域名, "*"表示允许任意域名使用该Web服务。
    config.addAllowedOrigin("*");
    // 是否发送Cookie信息
    config.setAllowCredentials(true);
    // 设置所允许的HTTP请求方法, "*"表示允许所有HTTP请求方法
    config.addAllowedMethod("*");
    // 设置所允许的请求头, "*"表示允许所有的请求头
    config.addAllowedHeader("*");
    config.addExposedHeader(HttpHeaders.SET_COOKIE);
    config.setMaxAge(3600L);
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}

需要注意的是,如果你工程中有拦截器,可能会有影响哦。

【2】SSM体系

这里比较麻烦,需要编写跨域过滤器并配置在web.xml中。

跨域过滤器:

// 跨域过滤器
public class CrosFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        String curOrigin = request.getHeader("Origin");
        StringBuffer requestURL = request.getRequestURL();
        System.out.println("跨域过滤器被执行,当前访问来源者为:" + curOrigin);
        System.out.println("跨域过滤器被执行,当前访问来源者为:" + requestURL.toString());
        // 设置响应头
        //该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接收任意域名的请求。
        response.setHeader("Access-Control-Allow-Origin", "http://localhost:8081");
        //该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法
        response.setHeader("Access-Control-Allow-Methods", "*");
        //预检间隔时间
        response.setHeader("Access-Control-Max-Age", "3600");
        //该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段
        //一旦自己设置了自定义请求头那么在服务端就不能统一放行设置为*,这样是不会通过校验的,
        // *一般校验的只有固定的请求头参数,如果是自定义的请求头自然不在这个列表中,所以如果是自定义请求头,后端需要将自定义头逐一校验,这样方能完成预校验
//        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,token,customercoderoute,authorization,conntectionid,Cookie,request-ajax");

        //Access-Control-Allow-Credentials:该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。
        // 默认情况下,Cookie不包括在CORS请求之中,设为True,
        // 即表示服务器明确许可,Cookie可以包含在请求中,一起发送给服务器。
        // 这个值也只能设为True,如果服务器不要浏览器发送Cookie,删除即可
        // Access-Control-Allow-Credentials为True的时候,Access-Control-Allow-Origin一定不能设置为“*”,否则报错
        response.setHeader("Access-Control-Allow-Credentials","true");
        response.setHeader("Access-Control-Expose-Headers", "*");

        // 浏览器默认会发起异常 OPTIONS 的请求方式 这个时候我们通过过滤器直接拦截返回200后就可以解决跨越问题
        if ("OPTIONS".equals(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
            return;
        }
        System.out.println("跨域过滤器被执行,chain.doFilter(request, response);" );
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {
    }
}

xml配置:

<filter>
    <filter-name>crosFilter</filter-name>
    <filter-class>com.jane.config.CrosFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>crosFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

可以看到两种体系下属性的设置基本一致的。

【3】springboot下设置跨域不生效的场景

如果你的项目中有其他拦截器影响了 CORS 的设置,导致全局 CORS 配置不起作用,可以通过调整拦截器的顺序或排除特定路径来解决这个问题。以下是一些可能的解决方案:

解决方案 1:调整拦截器顺序

确保 CORS 配置在所有其他拦截器之前应用。可以通过 Ordered 接口或 order 方法来指定顺序。

示例:使用 @Order(Ordered.HIGHEST_PRECEDENCE)

@Bean
@Order(Ordered.HIGHEST_PRECEDENCE) //解决拦截器影响跨域配置问题
public WebMvcConfigurer corsConfigurer(){
//        response.setHeader("Access-Control-Allow-Origin", "http://localhost:8081");
    return new WebMvcConfigurer() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**").
                    allowedOrigins("*"). //允许跨域的域名,可以用*表示允许任何域名使用
//                        allowedMethods("*"). //允许任何方法(post、get等)
                    allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS"). // 允许的HTTP方法
                    allowedHeaders("*"). //允许任何请求头
                    allowCredentials(true). //带上cookie信息
                    exposedHeaders(HttpHeaders.SET_COOKIE).maxAge(3600L);
            //maxAge(3600)表明在3600秒内,不需要再发送预检验请求,可以缓存该结果
        }
    };
}

解决方案 2:排除特定路径

如果你的拦截器只针对某些路径,可以将这些路径从 CORS 配置中排除。

示例:排除特定路径

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) {
        registry.addMapping("/**")
            .excludePathPatterns("/no-cors/**") // 排除这些路径
            .allowedOrigins("*")
            .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
            .allowedHeaders("*")
            .allowCredentials(true)
            .maxAge(3600);
    }
}

解决方案 3:在拦截器中处理 CORS

如果你的拦截器必须处理所有请求,可以在拦截器中处理 CORS 相关的响应头。

示例:在拦截器中/过滤器处理 CORS

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

import org.springframework.web.filter.OncePerRequestFilter;

public class CorsFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            filterChain.doFilter(request, response);
        }
    }
}

注册拦截器

然后在 Spring Boot 的配置类中注册这个拦截器。

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class WebConfig {

    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        FilterRegistrationBean<CorsFilter> registration = new FilterRegistrationBean<>(new CorsFilter());
        registration.addUrlPatterns("/*"); // 应用于所有 URL
        registration.setOrder(Ordered.HIGHEST_PRECEDENCE); // 最高的优先级
        return registration;
    }
}

这里的拦截器是一个广义概念,泛指可以根据路径匹配规则实现请求拦截/过滤的服务。如下是在一个拦截器的preHandle添加响应头实现跨域支持:

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    //拦截器跨域配置
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization,Token");
    response.setHeader("Access-Control-Allow-Credentials", "true");
    
    String token = request.getHeader(AUTH_HEADER_NAME);
    if (StringUtils.isEmpty(token)||isTokenExpired(token)) {
        Map<String, Object> errorResponse = new HashMap<>();
        errorResponse.put("code", 401);
        errorResponse.put("msg", "Token has expired");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
//                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);// response.setStatus(401); // Return 401 Unauthorized
        response.getWriter().write(JSONObject.toJSONString(errorResponse));
//                new ObjectMapper().writeValue(response.getOutputStream(), errorResponse);

        return false; // Stop processing the request
    }
    return true; // Continue processing the request
}

解决方案 4:使用 @CrossOrigin 注解

对于特定的控制器或方法,可以在类级别或方法级别使用 @CrossOrigin 注解。

示例:使用 @CrossOrigin 注解

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.RestController;

@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "*", allowedHeaders = "*", allowCredentials = "true")
public class MyController {

    @GetMapping("/protected")
    public String getProtectedResource() {
        return "Hello, Protected Resource!";
    }
}

总结

  1. 调整顺序:确保 CORS 配置在所有其他拦截器之前应用。
  2. 排除路径:如果某些路径不需要 CORS 支持,可以将这些路径排除。
  3. 在拦截器中处理 CORS:如果拦截器必须处理所有请求,可以在拦截器中添加 CORS 相关的响应头。
  4. 使用 @CrossOrigin 注解:对于特定的控制器或方法,可以在类级别或方法级别使用 @CrossOrigin 注解。

通过这些方法,你可以解决由于其他拦截器导致的 CORS 配置无效的问题。如果仍然存在问题,请提供更多关于你的项目结构和配置的信息,以便进一步诊断。

【4】允许所有来源、请求头和凭证案例

@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();

    // 使用 allowedOriginPatterns 代替 addAllowedOrigin 以支持通配符和凭证同时使用
    config.addAllowedOriginPattern("*");  // 允许所有来源
    
    // 凭证配置需要与来源模式配合使用
    config.setAllowCredentials(true);     // 允许发送Cookie
    
    // 允许所有请求头
    config.addAllowedHeader("*");         // 允许所有请求头
    
    // 允许所有HTTP方法
    config.addAllowedMethod("*");         // GET, POST, PUT 等
    
    // 暴露需要访问的响应头(可选)
    config.addExposedHeader(HttpHeaders.SET_COOKIE);
    
    // 预检请求缓存时间(秒)
    config.setMaxAge(3600L);
    
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}

关键优化点说明:

  1. 使用 addAllowedOriginPattern("*") 代替多个 addAllowedOrigin 调用,可以:

    • 支持所有来源的跨域请求
    • 兼容 setAllowCredentials(true) 配置(使用 addAllowedOrigin("*") 会导致与凭证配置冲突)
  2. 保留 addAllowedHeader("*") 实现允许所有请求头

  3. 其他优化保留项:

    • 保持凭证支持(Cookie、Authorization等)
    • 暴露必要的响应头
    • 维持预检请求缓存时间

注意:allowedOriginPatterns 是 Spring Framework 5.3+ 引入的特性,请确保你的 Spring Boot 版本 >= 2.4.x。如果使用旧版本,可以改为动态设置来源:

config.setAllowedOrigins(Arrays.asList("*")); 
// 但这样会与 setAllowCredentials(true) 冲突,需要二选一

springboot版本如下所示:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.3</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
### 集成SSMSpring Boot和Vue.js的技术方案 在实际开发中,集成 SSMSpring + Spring MVC + MyBatis)框架与 Spring Boot 和 Vue.js 是一种常见的全栈开发需求。以下是具体的实现方式: #### 1. 技术架构概述 SSM 框架是传统的 Java Web 开发技术栈,而 Spring Boot 则是对 Spring 框架的进一步封装,简化了配置过程。Vue.js 是一个渐进式前端框架[^3],可以灵活地构建用户界面。集成这三者时,通常采用前后端分离的架构设计。 - **后端**:使用 Spring Boot 替代传统的 SSM 框架,通过 MyBatis 或 JPA 进行数据库操作。 - **前端**:使用 Vue.js 构建独立的前端项目,通过 RESTful API 与后端交互。 --- #### 2. 后端部分:Spring Boot 配置 Spring Boot 已经内置了 SpringSpring MVC 的功能,因此可以直接替代 SSM 中的 SpringSpring MVC 部分[^1]。 - **引入依赖**:在 `pom.xml` 文件中添加必要的依赖项,例如: ```xml <dependencies> <!-- Spring Boot Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- MyBatis 数据库操作 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.3.0</version> </dependency> <!-- MySQL 数据库驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> </dependencies> ``` - **配置数据源**:在 `application.yml` 或 `application.properties` 文件中配置数据库连接信息: ```yaml spring: datasource: url: jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC username: root password: your_password driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*.xml ``` - **创建 RESTful 接口**:定义 Controller 层,提供 RESTful API 供前端调用。例如: ```java @RestController @RequestMapping("/api") public class UserController { @Autowired private UserService userService; @GetMapping("/users") public List<User> getAllUsers() { return userService.getAllUsers(); } } ``` --- #### 3. 前端部分:Vue.js 配置 Vue.js 是一个渐进式前端框架,可以单独构建前端项目并与后端通过 API 交互[^3]。 - **初始化项目**:使用 Vue CLI 初始化 Vue 项目: ```bash npm install -g @vue/cli vue create frontend cd frontend npm install axios --save # 用于发送 HTTP 请求 ``` - **配置 API 调用**:在 Vue 组件中通过 Axios 调用后端接口。例如: ```javascript <script> import axios from 'axios'; export default { data() { return { users: [] }; }, methods: { fetchUsers() { axios.get('http://localhost:8080/api/users') .then(response => { this.users = response.data; }) .catch(error => { console.error(error); }); } }, mounted() { this.fetchUsers(); } }; </script> ``` --- #### 4. 前后端整合 为了实现前后端的无缝整合,需要确保以下几点: - **问题**:如果前端和后端运行在不同的名或端口上,需要在 Spring Boot 中配置 CORS 支持。例如: ```java @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:8081") // 前端运行的地址 .allowedMethods("GET", "POST", "PUT", "DELETE"); } } ``` - **静态资源托管**:将 Vue.js 构建后的静态文件部署到 Spring Boot 的 `src/main/resources/static` 目录下[^3]。例如: ```bash npm run build cp -r dist/* src/main/resources/static/ ``` --- #### 5. 总结 通过上述步骤,可以成功集成 SSMSpring Boot 和 Vue.js。Spring Boot 替代了 SSM 的复杂配置,Vue.js 提供了强大的前端支持,二者结合形成了一个完整的全栈解决方案。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流烟默

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值