- 跨源资源共享 - MDN Web 文档术语表:Web 相关术语的定义 | MDN
- 浏览器的同源策略 - Web 安全 | MDN
- 交通银行1面:SpringBoot如何解决跨域问题?前言 大家好,我是Leo哥😎😎😎,今天我们开启一个新的专栏,聚 - 掘金
跨源资源共享(Cross-Origin Resource Sharing,CORS)是一个由一系列传输的 HTTP 标头组成的系统。这些 HTTP 标头决定浏览器是否阻止前端 JavaScript 代码获取跨源请求的响应。
同源安全策略默认阻止“跨源”获取资源。但是 CORS 给了 Web 服务器这样的权限,即服务器可以选择允许跨源请求访问到它们的资源。
CORS是一种由 W3C 标准定义的跨域请求机制,允许浏览器通过设置 HTTP 请求头和响应头来实现跨域访问。CORS 是浏览器针对跨域请求的安全策略扩展,通过服务端显式声明哪些资源可以被特定来源访问,从而安全地实现跨域资源共享
。
SpringBoot 配置 CORS
通过 WebMvcConfigurer 全局配置
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 GlobalCorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 匹配所有路径
.allowedOrigins("http://example.com", "http://another-domain.com") // 允许的跨域域名
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允许的请求方法
.allowedHeaders("*") // 允许的请求头
.allowCredentials(true) // 是否允许发送 Cookie
.maxAge(3600); // 预检请求的缓存时间
}
}
通过 @CrossOrigin注解局部配置
单个控制器方法
@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/hello")
@CrossOrigin(origins = "http://example.com", maxAge = 3600)
public String hello() {
return "world";
}
}
全控制器
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://example.com", allowedHeaders = "*", methods = {RequestMethod.GET, RequestMethod.POST})
public class ApiController {
@GetMapping("/hello")
@CrossOrigin(origins = "http://example.com", maxAge = 3600)
public String hello() {
return "world";
}
}
自定义过滤器
更高级的跨域控制,比如动态允许某些域名跨域,可以通过自定义 CorsFilter 来实现
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 强制类型转换为 HttpServletRequest 和 HttpServletResponse
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// 添加 CORS 响应头
httpResponse.setHeader("Access-Control-Allow-Origin", "*"); // 允许所有来源访问
httpResponse.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); // 允许的 HTTP 方法
httpResponse.setHeader("Access-Control-Allow-Headers", "Origin, Content-Type, Accept, Authorization"); // 允许的请求头
httpResponse.setHeader("Access-Control-Allow-Credentials", "true"); // 是否允许携带 Cookie
// 处理 OPTIONS 请求(CORS 预检请求)
if ("OPTIONS".equalsIgnoreCase(httpRequest.getMethod())) {
httpResponse.setStatus(HttpServletResponse.SC_OK);
return;
}
// 继续执行下一个过滤器链
chain.doFilter(request, response);
}
}
验证方法
打开浏览器的开发者工具,查看请求和响应头,确保响应中包含以下头信息:
- Access-Control-Allow-Origin
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers
- Access-Control-Allow-Credentials
注意事项
- Access-Control-Allow-Origin 设置:
- 如果需要限制特定的来源访问,可以将 "*" 替换为具体的域名,例如 "example.com"。
- 安全性:
- 如果允许所有来源访问(*),可能存在安全风险,尤其是在涉及敏感数据的场景下。
- OPTIONS 请求:
-
如果未正确处理 OPTIONS 请求,可能导致前端跨域失败。
-