在Spring Boot项目中,在前端和后端部署在不同的域下,需要在接口层配置CORS(跨源资源共享)支持,允许跨域请求。

359 阅读4分钟

跨域资源共享(CORS)是一个W3C规范,它定义了一种浏览器和服务器交互的方式来确定是否允许跨源请求。当Web应用的前端和后端部署在不同的域(或端口、协议)下时,浏览器出于安全考虑会限制前端JavaScript代码访问其他源的资源。为了实现跨域请求,后端服务需要在HTTP响应中包含一些特定的头信息来指示浏览器允许跨域访问。

在Spring Boot项目中,你可以通过以下步骤来配置CORS支持:

1. 使用@CrossOrigin注解

你可以在Controller类或方法上使用@CrossOrigin注解来允许跨域请求。例如:

@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://your-frontend-domain.com", allowedMethods = {"GET", "POST"})
public class YourApiController {
    // ... 方法定义
}

这个注解将允许来自http://your-frontend-domain.com的GET和POST请求访问这个Controller的所有方法。

2. 全局CORS配置

如果你想要全局配置CORS,而不是在每个Controller或方法上单独配置,你可以创建一个配置类并重写WebMvcConfigureraddCorsMappings方法:

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://your-frontend-domain.com")
                .allowedMethods("GET", "POST", "PUT", "DELETE")
                .allowedHeaders("*")
                .allowCredentials(true)
                .maxAge(168000); // 缓存预检请求的结果24小时
    }
}

这个配置将允许来自http://your-frontend-domain.com的所有HTTP方法访问应用的任何路径,并允许携带凭证(cookies等)。

3. 自定义CORS过滤器

在某些情况下,你可能需要更细粒度的控制,这时可以创建一个自定义的CORS过滤器:

@Component
public class CustomCorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "http://your-frontend-domain.com");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, content-type");
        chain.doFilter(req, res);
    }
}

然后,你需要将这个过滤器注册到Spring Security中(如果你使用了Spring Security):

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomCorsFilter corsFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // ... 其他安全配置
            .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class);
    }
}

注意事项:

  • 允许跨域请求时要小心,确保只允许必要的源和方法,以防止潜在的安全风险。
  • 如果你的应用使用了Spring Security,确保CORS配置与Spring Security的配置兼容。
  • 在生产环境中,通常不会允许所有头部(Access-Control-Allow-Headers: *),而是应该指定具体允许的头部。
  • 如果你的应用需要处理带凭证的请求(如cookies或HTTP认证),确保设置Access-Control-Allow-Credentialstrue,并在Access-Control-Allow-Origin中指定具体的域名,而不是使用通配符*

配置完成后,你的Spring Boot应用应该能够处理来自指定前端域的跨域请求了。记得在测试配置时,使用浏览器的开发者工具查看网络请求的响应头,确保CORS相关的头信息已经正确设置。

一个更简单的CORS配置示例

使用Spring Boot并希望允许所有来源的跨域请求。请注意,出于安全考虑,在生产环境中允许所有来源通常不是一个好主意,但在开发或测试环境中可能是可以接受的。

以下是如何在Spring Boot应用中全局启用CORS的简单步骤:

  1. 创建一个配置类,并实现WebMvcConfigurer接口。
  2. 重写addCorsMappings方法,以添加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 CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 添加映射路径,我们这里使用的是"/**",表示对所有的路径都进行处理
        registry.addMapping("/**")
                // 允许跨域请求的域名或IP,星号代表允许所有
                .allowedOrigins("*")
                // 请求允许的方法,如POST, GET, PUT, DELETE等
                .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
                // 预检间隔时间
                .maxAge(168000)
                // 允许头部设置
                .allowedHeaders("*")
                // 是否允许发送cookie
                .allowCredentials(true);
    }
}

在这个例子中,我们允许所有来源(*)对所有路径(/**)发起跨域请求,并允许所有HTTP方法(如POST、GET、PUT等)。allowedHeaders("*")允许所有的请求头,而allowCredentials(true)则允许携带凭证(如cookies)的请求。

将上述配置类添加到Spring Boot项目中后,应该能够处理来自任何域的跨域请求了。

请再次强调,允许所有来源的跨域请求在生产环境中是不安全的,应该明确指定允许的域。此外,如果不需要允许携带凭证的请求,也可以将allowCredentials(true)改为allowCredentials(false),这通常是一个更安全的做法。