SpringBoot3解决跨域请求的方案小结

 更新时间:2024年07月31日 10:34:21   作者:Yaml墨韵  
解决跨域请求,主要有JSONP,iframe,window.name,CORS等方式,其中CORS方式是最常用的跨域实现方式,而且是对各种请求方法、各种数据请求类型都是完美支持的,本文介绍了SpringBoot3解决跨域请求的方案小结,需要的朋友可以参考下

在Spring Boot 3中,解决跨域请求(CORS,Cross-Origin Resource Sharing)的问题主要有以下几种方式:

1. 使用@CrossOrigin注解

你可以直接在Controller类或者具体的请求处理方法上使用@CrossOrigin注解来允许跨域请求。

@RestController  
@RequestMapping("/user")  
@CrossOrigin(origins = "*") // 允许所有来源的请求跨域  
public class UserController {  
    // ...  
}

在这个例子中,@CrossOrigin注解被添加到了控制器类上,表示这个控制器下的所有方法都允许来自http://example.com的GET和POST请求。你也可以将注解添加到特定的方法上,以对该方法应用CORS配置。

2. 全局配置CORS

如果你希望全局配置CORS,而不是在每个Controller或方法上单独配置,你可以创建一个配置类来实现WebMvcConfigurer接口,并重写addCorsMappings方法。

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 CorsConfig implements WebMvcConfigurer {  
  
    @Override  
    public void addCorsMappings(CorsRegistry registry) {  
        // 添加映射路径  
        registry.addMapping("/**")  
                .allowedOrigins("*") // 允许哪些域的请求,星号代表允许所有  
                .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") // 允许的方法  
                .allowedHeaders("*") // 允许的头部设置  
                .allowCredentials(true) // 是否发送cookie  
                .maxAge(168000); // 预检间隔时间  
    }  
}

在这个配置中,addMapping("/**")表示对所有的路径都应用CORS配置。allowedOrigins("*")表示允许所有来源的访问,这在生产环境中可能不是最佳实践,通常你会指定具体的域名。allowedMethods定义了允许的HTTP方法,allowedHeaders定义了允许的HTTP头部,allowCredentials(true)表示是否允许携带凭证(cookies, HTTP认证及客户端SSL证明等),maxAge则用于设置预检请求的有效期。

3. 使用Filter实现CORS

你也可以通过实现Filter接口来自定义CORS处理逻辑。

import javax.servlet.*;  
import javax.servlet.http.HttpServletResponse;  
import java.io.IOException;  
  
public class SimpleCorsFilter implements Filter {  
  
    @Override  
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)  
            throws IOException, ServletException {  
        HttpServletResponse response = (HttpServletResponse) res;  
        response.setHeader("Access-Control-Allow-Origin", "http://example.com");  
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");  
        response.setHeader("Access-Control-Max-Age", "3600");  
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with");  
        chain.doFilter(req, res);  
    }  
  
    @Override  
    public void init(FilterConfig filterConfig) {}  
  
    @Override  
    public void destroy() {}  
}

然后需要在配置类中注册这个Filter。

import org.springframework.boot.web.servlet.FilterRegistrationBean;  
import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  
  
@Configuration  
public class FilterConfig {  
  
    @Bean  
    public FilterRegistrationBean<SimpleCorsFilter> corsFilter() {  
        FilterRegistrationBean<SimpleCorsFilter> registrationBean = new FilterRegistrationBean<>();  
        registrationBean.setFilter(new SimpleCorsFilter());  
        registrationBean.addUrlPatterns("/*");  
        return registrationBean;  
    }  
}

4. 使用拦截器(Interceptor)

如果需要更复杂的CORS逻辑,你可以创建一个拦截器来处理CORS请求。拦截器允许你在请求处理之前或之后添加逻辑。

import org.springframework.web.servlet.HandlerInterceptor;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
  
public class CorsInterceptor implements HandlerInterceptor {  
  
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {  
        response.setHeader("Access-Control-Allow-Origin", "http://example.com");  
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");  
        response.setHeader("Access-Control-Allow-Headers", "*");  
        // 其他CORS相关的响应头设置  
        return true;  
    }  
}

然后,你需要在配置类中注册这个拦截器: 

import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.context.annotation.Configuration;  
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;  
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;  
  
@Configuration  
public class WebConfig implements WebMvcConfigurer {  
  
    @Autowired  
    private CorsInterceptor corsInterceptor;  
  
    @Override  
    public void addInterceptors(InterceptorRegistry registry) {  
        registry.addInterceptor(corsInterceptor).addPathPatterns("/**");  
    }  
}
  • 当设置allowedHeaders("*")时,实际上浏览器会发送实际请求头而不是*。出于安全考虑,最好明确指定允许的头部。
  • 在生产环境中,确保不要过于宽松地配置CORS,只允许必要的源和方法。
  • 如果你的应用部署在代理服务器后面(如Nginx或Apache),可能还需要在代理服务器上配置CORS。

5. 响应体(Response Body)来设置CORS

虽然这种方式不如前面提到的几种方法直接和常用,但在某些特殊场景下,你可能需要手动控制响应头来实现跨域。

具体实现时,你可以在Controller的方法中,通过HttpServletResponse对象来设置Access-Control-Allow-Origin等CORS相关的HTTP头。

import javax.servlet.http.HttpServletResponse;  
import org.springframework.web.bind.annotation.GetMapping;  
import org.springframework.web.bind.annotation.RestController;  
  
@RestController  
public class MyController {  
  
    @GetMapping("/data")  
    public String getData(HttpServletResponse response) {  
        // 设置允许跨域的来源  
        response.setHeader("Access-Control-Allow-Origin", "http://example.com");  
        // 设置允许的方法(GET, POST, PUT, DELETE等)  
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");  
        // 设置允许的头信息  
        response.setHeader("Access-Control-Allow-Headers", "*");  
        // 设置预检请求的有效期  
        response.setHeader("Access-Control-Max-Age", "3600");  
          
        // 返回数据  
        return "Data";  
    }  
}

需要注意的是,手动设置响应头的方式相对繁琐,且容易遗漏某些必要的头信息,导致CORS配置不完整。因此,在实际开发中,推荐使用前面提到的方法,它们更为直接且易于管理。

此外,如果你正在使用Spring Security,还需要确保Spring Security的配置不会阻止跨域请求的处理。在某些情况下,你可能需要在Spring Security的配置中允许特定的CORS请求。

6. 通过自定义ResponseBodyAdvice

ResponseBodyAdvice是Spring MVC提供的一个接口,允许你在Controller方法返回响应体之前对其进行修改。虽然它本身不是专为CORS设计的,但你可以利用它在返回响应之前添加CORS相关的HTTP头。

下面是一个简单的示例,展示了如何通过实现ResponseBodyAdvice接口来添加CORS头:

import org.springframework.core.MethodParameter;  
import org.springframework.http.MediaType;  
import org.springframework.http.server.ServerHttpRequest;  
import org.springframework.http.server.ServerHttpResponse;  
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;  
  
import java.lang.reflect.Type;  
  
public class CorsResponseBodyAdvice implements ResponseBodyAdvice<Object> {  
  
    @Override  
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {  
        // 支持所有返回类型  
        return true;  
    }  
  
    @Override  
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,  
                                   Class<? extends HttpMessageConverter<?>> selectedConverterType,  
                                   ServerHttpRequest request, ServerHttpResponse response) {  
        // 设置CORS相关的HTTP头  
        response.getHeaders().set("Access-Control-Allow-Origin", "http://example.com");  
        response.getHeaders().set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");  
        response.getHeaders().set("Access-Control-Allow-Headers", "*");  
        // 如果有需要,还可以设置其他CORS相关的头,比如预检请求的有效期等  
          
        // 返回原始的body,不做修改  
        return body;  
    }  
}

然后,你需要在Spring Boot的配置中注册这个ResponseBodyAdvice

import org.springframework.context.annotation.Configuration;  
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;  
  
@Configuration  
public class WebConfig implements WebMvcConfigurer {  
  
    @Override  
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {  
        // 注册你的ResponseBodyAdvice  
        converters.forEach(converter -> {  
            if (converter instanceof MappingJackson2HttpMessageConverter) {  
                ((MappingJackson2HttpMessageConverter) converter).setResponseBodyAdvice(new CorsResponseBodyAdvice());  
            }  
        });  
    }  
}

这种方法的优点在于它可以全局地应用于所有Controller的响应,而无需在每个Controller或方法上单独设置。然而,它同样也有一些局限性,比如你可能需要手动处理一些CORS的细节,并且这种方式不如使用Spring提供的CORS支持那么直接和灵活。

在选择解决方案时,应该根据项目的具体需求和团队的偏好来权衡各种方法的优缺点。如果项目中有大量的Controller需要处理跨域请求,并且希望有一个统一且全局的解决方案,那么使用WebMvcConfigurer或CorsFilter可能是更好的选择。如果只需要在特定的Controller或方法上处理跨域请求,那么使用@CrossOrigin注解可能更为简单直接。

以上就是SpringBoot3解决跨域请求的方案小结的详细内容,更多关于SpringBoot3跨域请求的资料请关注脚本之家其它相关文章!

相关文章

  • java基于swing实现的五子棋游戏代码

    java基于swing实现的五子棋游戏代码

    这篇文章主要介绍了java基于swing实现的五子棋游戏代码,主要涉及图形界面与数组的用法,有不错的参考借鉴价值,需要的朋友可以参考下
    2014-11-11
  • Java并发系列之AbstractQueuedSynchronizer源码分析(概要分析)

    Java并发系列之AbstractQueuedSynchronizer源码分析(概要分析)

    这篇文章主要为大家详细介绍了Java并发系列之AbstractQueuedSynchronizer源码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • Spring中WebDataBinder使用详解

    Spring中WebDataBinder使用详解

    这篇文章主要为大家详细介绍了Spring中WebDataBinder的使用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • MyBatis Plus整合Redis实现分布式二级缓存的问题

    MyBatis Plus整合Redis实现分布式二级缓存的问题

    Mybatis内置的二级缓存在分布式环境下存在分布式问题,无法使用,但是我们可以整合Redis来实现分布式的二级缓存,这篇文章给大家介绍MyBatis Plus整合Redis实现分布式二级缓存,感兴趣的朋友跟随小编一起看看吧
    2023-11-11
  • 判断二叉树是否为完全二叉树的实例

    判断二叉树是否为完全二叉树的实例

    这篇文章主要介绍了判断二叉树是否为完全二叉树的实例的相关资料,需要的朋友可以参考下
    2017-05-05
  • Java中ShardingSphere 数据分片的实现

    Java中ShardingSphere 数据分片的实现

    其实很多人对分库分表多少都有点恐惧,我们今天用ShardingSphere 给大家演示数据分片,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • 详解Spring中bean的几种注入方式

    详解Spring中bean的几种注入方式

    这篇文章主要介绍了详解Spring中bean的几种注入方式,主要介绍了4种注入,主要有属性注入、构造函数注入、工厂方法注入,非常具有实用价值,需要的朋友可以参考下
    2018-06-06
  • Java中的堆和栈示例详解

    Java中的堆和栈示例详解

    在Java中,堆(Heap)和栈(Stack)是两种不同的内存区域,本文给大家介绍Java中的堆和栈,结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧
    2025-09-09
  • JAVA发送HTTP请求的四种方式总结

    JAVA发送HTTP请求的四种方式总结

    这篇文章主要给大家介绍了关于JAVA发送HTTP请求的多种方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • 一文深入理解Java中的深拷贝机制

    一文深入理解Java中的深拷贝机制

    在Java编程中,我们经常需要处理对象的复制问题,深拷贝和浅拷贝是两种常见的复制方式,它们在内存管理和对象引用方面存在不同特点,本文将带大家深入探究Java中的深拷贝机制,需要的朋友可以参考下
    2023-09-09

最新评论