feat: 新增全局CORS跨域过滤器,支持设备后台跨域访问网关
- 新增 CorsFilter(@Component(index=-200)最高优先级) - OPTIONS预检请求:动态回显 Access-Control-Request-Headers,直接短路返回200不透传源服务器 - 其他请求:响应头补充 Access-Control-Allow-Origin 等CORS头 - 解决jeecg vue3前端自定义头(x-version等)被CORS拦截问题 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
- `/sys/watchUserLogin` → **本地处理**:解密验证设备密码(防伪造)+ 单飞换 token + Redis 缓存
|
||||
- 其余业务接口 → **手动 HttpUtils 透传**至源服务器 `http://10.10.10.228:29999`
|
||||
- token 失效三重自愈:10秒主动探活 + 预过期刷新 + 业务接口 401 被动兜底
|
||||
- **全局 CORS**:CorsFilter 处理跨域(设备后台跨域访问网关),OPTIONS 预检直接短路返回
|
||||
|
||||
## 技术栈
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.renkang.gateway.filter;
|
||||
|
||||
import org.noear.solon.annotation.Component;
|
||||
import org.noear.solon.core.handle.Context;
|
||||
import org.noear.solon.core.handle.Filter;
|
||||
import org.noear.solon.core.handle.FilterChain;
|
||||
|
||||
/**
|
||||
* 全局 CORS 跨域过滤器。
|
||||
* <p>
|
||||
* 健康设备后台(如 http://10.10.10.228:23001)跨域访问本网关时,浏览器要求响应带
|
||||
* Access-Control-Allow-Origin 等头,否则被拦截。
|
||||
* <p>
|
||||
* 处理策略(CORS 最佳实践,避免逐个枚举允许的头):
|
||||
* <ul>
|
||||
* <li>OPTIONS 预检请求:读取客户端请求的 Access-Control-Request-Headers,
|
||||
* 原样回显到 Access-Control-Allow-Headers,并返回 200,不透传源服务器</li>
|
||||
* <li>其他请求:放行到后续 Controller,响应头补充 CORS 头</li>
|
||||
* </ul>
|
||||
* 这样无论前端(jeecg vue3 等)加什么自定义头(X-Version、X-TIMESTAMP、X-Sign 等)都不会被拦。
|
||||
*
|
||||
* @author renkang
|
||||
*/
|
||||
@Component(index = -200) // index 越小越先执行,确保 CORS 在业务透传前处理
|
||||
public class CorsFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public void doFilter(Context ctx, FilterChain chain) throws Throwable {
|
||||
// 统一设置基础 CORS 响应头(OPTIONS 和普通请求都需要)
|
||||
ctx.headerSet("Access-Control-Allow-Origin", "*");
|
||||
ctx.headerSet("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH");
|
||||
// 动态回显客户端预检请求的头,避免逐个枚举(最佳实践)
|
||||
String reqHeaders = ctx.header("Access-Control-Request-Headers");
|
||||
if (reqHeaders != null && !reqHeaders.isEmpty()) {
|
||||
ctx.headerSet("Access-Control-Allow-Headers", reqHeaders);
|
||||
} else {
|
||||
// 无预检头时给一个兜底白名单(含 jeecg vue3 常用头)
|
||||
ctx.headerSet("Access-Control-Allow-Headers",
|
||||
"Content-Type, Authorization, X-Access-Token, X-Requested-With, X-Version, X-TIMESTAMP, X-Sign, token, Accept, Origin");
|
||||
}
|
||||
ctx.headerSet("Access-Control-Max-Age", "3600");
|
||||
|
||||
// OPTIONS 预检请求直接短路返回,不透传源服务器(降低源服务器压力)
|
||||
if ("OPTIONS".equalsIgnoreCase(ctx.method())) {
|
||||
ctx.status(200);
|
||||
return; // 不进入后续过滤器/Controller
|
||||
}
|
||||
|
||||
// 其他请求放行到后续处理(GatewayController 透传 / TokenController)
|
||||
chain.doFilter(ctx);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user