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

1. 使用@CrossOrigin注解

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

import org.springframework.web.bind.annotation.CrossOrigin;  
import org.springframework.web.bind.annotation.GetMapping;  
import org.springframework.web.bind.annotation.RestController;  
  
@RestController  
@CrossOrigin(origins = "http://example.com", methods = {RequestMethod.GET, RequestMethod.POST})  
public class MyController {  
  
    @GetMapping("/myEndpoint")  
    public String myEndpoint() {  
        return "Hello, CORS!";  
    }  
}

在这个例子中,@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。
03-27 08:12