## 前言
在前后端分离的开发中,跨域问题是每个开发者都会遇到的经典问题。当你看到这个熟悉的错误时:
Access to XMLHttpRequest at '********' from origin '********' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
恭喜你,又一次踩到了CORS的坑。今天我们来彻底解决这个问题,用最简单粗暴的方式!
问题分析
什么是CORS?
CORS(Cross-Origin Resource Sharing,跨源资源共享)是一种机制,它使用额外的HTTP头来告诉浏览器,让运行在一个域上的Web应用被准许访问来自不同源服务器上的指定资源。
为什么会出现跨域问题?
浏览器的同源政策限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。当协议、域名、端口任意一个不同时,就会产生跨域问题。
预检请求(Preflight Request)
对于复杂请求,浏览器会先发送一个OPTIONS请求进行预检,确认服务器是否允许跨域访问。这就是问题的关键所在!
直接使用 Filter 彻底解决此问题,绕过一起阻碍,专治各种不服气(直接复制可用)
特别说明,之前版本中的 "Access-Control-Allow-Headers","*" 存在问题,需要适配处理,否则在前端发起请求时特定情况下会出现异常。 请查阅更新后的代码。
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.io.IOException;
/**
* CORS跨域过滤器 - 简单粗暴解决所有跨域问题
*/
@Slf4j
@Order(-1) // 确保在所有Filter之前执行
@Component
public class CORSFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("CORSFilter 初始化成功 - 全局跨域已启用");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String requestUrl = httpRequest.getRequestURL().toString();
String requestIp = IPUtils.getIpAddr(httpRequest);
String httpMethod = httpRequest.getMethod();
String origin = httpRequest.getHeader("Origin");
if (origin != null && !origin.isEmpty()) {
httpResponse.setHeader("Access-Control-Allow-Origin", origin);
httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpResponse.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
// 不能写 "*"
String reqHeaders = httpRequest.getHeader("Access-Control-Request-Headers");
httpResponse.setHeader("Access-Control-Allow-Headers", Objects.requireNonNullElse(reqHeaders, "Content-Type, Authorization"));
httpResponse.setHeader("Access-Control-Max-Age", "3600");
}
// 预检请求直接返回
if ("OPTIONS".equalsIgnoreCase(httpRequest.getMethod())) {
httpResponse.setStatus(HttpServletResponse.SC_OK);
return;
}
// 继续处理其他请求
chain.doFilter(request, response);
}
@Override
public void destroy() {
log.info("CORSFilter 销毁");
}
}
1021



被折叠的 条评论
为什么被折叠?



