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。如果你有任何问题或建议,欢迎在评论区留言讨论!下次见!
参考资料:
(以上文档内容已引用,未插入外部链接)