Spring Boot中的跨域资源共享(CORS)配置:@CrossOrigin与CorsFilter

Spring Boot中的跨域资源共享(CORS)配置:@CrossOrigin与CorsFilter

开场白

各位小伙伴们,大家好!今天咱们来聊聊Spring Boot中一个非常实用的功能——跨域资源共享(CORS)。相信很多同学在开发前后端分离的应用时,都遇到过跨域问题。浏览器默认是不允许从一个域名下的页面请求另一个域名的资源的,这就像你家的门禁系统,防止外人随便进来。但是,有时候我们确实需要让不同的域名之间互相通信,这时候就需要用到CORS了。

今天我们主要会讲两个东西:@CrossOrigin注解和CorsFilter类。这两个工具都能帮我们解决跨域问题,但它们的使用场景和配置方式有所不同。接下来,我会通过一些轻松诙谐的语言和代码示例,带大家深入了解这两者的区别和用法。

什么是CORS?

在正式开始之前,我们先简单了解一下什么是CORS。CORS(Cross-Origin Resource Sharing)是一种机制,它允许服务器明确地告诉浏览器,哪些外部域名可以访问它的资源。浏览器会根据这些信息决定是否允许跨域请求。

举个例子,假设你有一个前端应用部署在https://example.com,而后端API部署在https://api.example.com。当你从https://example.com发起一个HTTP请求到https://api.example.com时,浏览器会检查后端API是否允许来自https://example.com的请求。如果允许,浏览器就会正常发送请求;如果不允许,浏览器会阻止请求并抛出错误。

CORS的工作原理是通过HTTP头来实现的。常见的CORS响应头包括:

  • Access-Control-Allow-Origin: 指定允许访问的源(域名、协议和端口),或者使用*表示允许所有源。
  • Access-Control-Allow-Methods: 指定允许的HTTP方法(如GET、POST、PUT等)。
  • Access-Control-Allow-Headers: 指定允许的自定义请求头。
  • Access-Control-Max-Age: 指定预检请求的有效期,单位为秒。

了解了这些基本概念后,我们就可以开始学习如何在Spring Boot中配置CORS了。

使用@CrossOrigin注解

1. 简单的跨域配置

@CrossOrigin注解是最简单的CORS配置方式之一。你可以直接在控制器的方法上使用它,来为特定的API接口启用CORS支持。下面是一个简单的例子:

@RestController
@RequestMapping("/api")
public class MyController {

    @GetMapping("/data")
    @CrossOrigin(origins = "https://example.com")
    public ResponseEntity<String> getData() {
        return ResponseEntity.ok("Hello, World!");
    }
}

在这个例子中,@CrossOrigin(origins = "https://example.com")表示只允许来自https://example.com的请求访问这个API。如果你想要允许所有来源的请求,可以将origins设置为*

@CrossOrigin(origins = "*")

2. 配置多个来源

如果你想允许多个来源的请求,可以传递一个字符串数组给origins参数:

@CrossOrigin(origins = {"https://example.com", "https://another-domain.com"})

3. 配置允许的HTTP方法

除了指定来源,你还可以通过methods参数来限制允许的HTTP方法。例如,只允许GET和POST请求:

@CrossOrigin(origins = "https://example.com", methods = {RequestMethod.GET, RequestMethod.POST})

4. 配置允许的请求头

如果你的API需要处理自定义的请求头,可以通过allowedHeaders参数来指定允许的头:

@CrossOrigin(origins = "https://example.com", allowedHeaders = {"Authorization", "Content-Type"})

5. 配置暴露的响应头

有时候,前端需要访问某些自定义的响应头。你可以通过exposedHeaders参数来指定哪些响应头可以被前端访问:

@CrossOrigin(origins = "https://example.com", exposedHeaders = {"X-Custom-Header"})

6. 配置预检请求的有效期

对于复杂的跨域请求,浏览器会先发送一个预检请求(OPTIONS请求),以确认服务器是否允许实际的请求。你可以通过maxAge参数来设置预检请求的有效期,避免频繁发送预检请求:

@CrossOrigin(origins = "https://example.com", maxAge = 3600)

7. 全局配置

如果你不想在每个API方法上都加上@CrossOrigin注解,可以在类级别使用它,这样整个控制器的所有方法都会启用CORS:

@CrossOrigin(origins = "https://example.com")
@RestController
@RequestMapping("/api")
public class MyController {
    // API methods...
}

不过,@CrossOrigin注解的最大缺点是它只能针对特定的API进行配置。如果你有多个API需要统一的CORS策略,或者需要更复杂的配置,那么CorsFilter可能是更好的选择。

使用CorsFilter

1. 创建全局CORS过滤器

CorsFilter是一个更强大的工具,它可以在应用程序的全局范围内配置CORS。你可以通过创建一个CorsConfigurationSource来定义CORS规则,并将其注册为一个过滤器。下面是一个完整的示例:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CorsConfig {

    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowCredentials(true);  // 允许携带凭证(如Cookie)
        corsConfiguration.addAllowedOrigin("https://example.com");  // 允许的来源
        corsConfiguration.addAllowedHeader("*");  // 允许所有请求头
        corsConfiguration.addAllowedMethod("*");  // 允许所有HTTP方法

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);  // 应用于所有路径

        return new CorsFilter(source);
    }
}

在这个例子中,我们创建了一个全局的CORS过滤器,允许来自https://example.com的请求访问所有的API路径。你可以根据需要调整corsConfiguration中的参数,比如允许的来源、请求头、HTTP方法等。

2. 针对特定路径的CORS配置

如果你只想为某些特定的API路径启用CORS,可以在registerCorsConfiguration方法中指定路径模式。例如,只允许访问/api/*路径下的API:

source.registerCorsConfiguration("/api/**", corsConfiguration);

3. 动态配置CORS

有时候,你可能需要根据不同的请求动态地配置CORS规则。你可以通过实现CorsConfigurationSource接口来实现这一点。下面是一个简单的例子:

import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsConfigurationSource;

@Configuration
public class DynamicCorsConfig {

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        // 定义一个默认的CORS配置
        CorsConfiguration defaultConfig = new CorsConfiguration();
        defaultConfig.setAllowCredentials(true);
        defaultConfig.addAllowedOrigin("https://example.com");
        defaultConfig.addAllowedHeader("*");
        defaultConfig.addAllowedMethod("*");

        // 为所有路径应用默认配置
        source.registerCorsConfiguration("/**", defaultConfig);

        // 为特定路径定义不同的CORS配置
        CorsConfiguration specialConfig = new CorsConfiguration();
        specialConfig.setAllowCredentials(true);
        specialConfig.addAllowedOrigin("https://special-domain.com");
        specialConfig.addAllowedHeader("Authorization");
        specialConfig.addAllowedMethod("GET");

        source.registerCorsConfiguration("/special/**", specialConfig);

        return source;
    }
}

在这个例子中,我们为/special/**路径定义了一个特殊的CORS配置,而其他路径则使用默认的CORS配置。

4. 处理凭证(Credentials)

当涉及到身份验证时,CORS配置中必须允许携带凭证(如Cookie)。你需要在CorsConfiguration中设置setAllowCredentials(true),并且确保origins参数中只包含可信的来源。否则,浏览器会拒绝携带凭证的跨域请求。

corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedOrigin("https://trusted-domain.com");

5. CORS与安全

虽然CORS可以让我们灵活地控制跨域请求,但它也带来了安全风险。特别是当你允许携带凭证时,必须确保只信任可靠的来源。否则,恶意网站可能会利用CORS漏洞进行跨站请求伪造(CSRF)攻击。因此,在配置CORS时,务必谨慎选择允许的来源和请求头。

总结

好了,今天的讲座就到这里啦!我们详细介绍了Spring Boot中两种常见的CORS配置方式:@CrossOrigin注解和CorsFilter类。@CrossOrigin适合简单的跨域需求,而CorsFilter则提供了更强大的全局配置能力,适用于复杂的应用场景。

希望这篇文章能帮助大家更好地理解和使用CORS。如果你有任何问题或建议,欢迎在评论区留言讨论!下次见!


参考资料:

(以上文档内容已引用,未插入外部链接)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注