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字符缓冲流面试精讲

    java字符缓冲流面试精讲

    这篇文章主要为大家介绍了java中字符缓冲流面试精讲,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • 使用Lombok的@Builder注解带来的两大坑

    使用Lombok的@Builder注解带来的两大坑

    这篇文章主要介绍了使用Lombok的@Builder注解带来的两大坑,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • Java构造器(构造方法)与方法区别说明

    Java构造器(构造方法)与方法区别说明

    这篇文章主要介绍了Java构造器(构造方法)与方法区别说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • 详解Spring学习之编程式事务管理

    详解Spring学习之编程式事务管理

    本篇文章主要介绍了详解Spring学习之编程式事务管理,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • mybatis-plus getOne和逻辑删除问题详解

    mybatis-plus getOne和逻辑删除问题详解

    这篇文章主要介绍了mybatis-plus getOne和逻辑删除,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • IDEA在Maven项目中使用本地jar包的方法

    IDEA在Maven项目中使用本地jar包的方法

    我们在拿到旧项目的时候,经常会遇到一种情况,就是这个项目的maven中依赖了一个本地的jar包,这种情况就需要引入这个jar包,所以本文给大家介绍了IDEA在Maven项目中使用本地jar包的方法,需要的朋友可以参考下
    2024-04-04
  • SpringBoot使用Shiro实现动态加载权限详解流程

    SpringBoot使用Shiro实现动态加载权限详解流程

    本文小编将基于 SpringBoot 集成 Shiro 实现动态uri权限,由前端vue在页面配置uri,Java后端动态刷新权限,不用重启项目,以及在页面分配给用户 角色 、 按钮 、uri 权限后,后端动态分配权限,用户无需在页面重新登录才能获取最新权限,一切权限动态加载,灵活配置
    2022-07-07
  • 如何在Java中使用标准库创建临时文件

    如何在Java中使用标准库创建临时文件

    有时候我们程序运行时需要产生中间文件,但是这些文件只是临时用途,并不做长久保存,我们可以使用临时文件,不需要长久保存,这篇文章主要给大家介绍了关于如何在Java中使用标准库创建临时文件的相关资料,需要的朋友可以参考下
    2023-10-10
  • Java线程池实现带返回值的方式方法

    Java线程池实现带返回值的方式方法

    在Java中,线程池是一种重要的多线程处理方式,可以有效管理和重用线程,提高程序的性能和效率,有时候我们需要在多线程处理中获取线程的返回值,本文将介绍如何使用线程池实现带返回值的方式方法,需要的朋友可以参考下
    2024-09-09
  • 浅谈JAVA 类加载器

    浅谈JAVA 类加载器

    这篇文章主要介绍了JAVA 类加载器的的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-06-06

最新评论