zhizhijie
2026-09-16 0d2a5fc482ba7ffaaefa6276e2475727e7160753
fix(cors): 放行内网网段来源,修复局域网 IP 访问时登录 403

浏览器 POST/PUT/DELETE 必带 Origin(GET 不带);9-14 跨域收紧后白名单只列了
http://localhost:8080 与 http://127.0.0.1:8080,经 dev-server 代理转发来的
Origin: http://192.168.177.26:8080 命中不了白名单,被 CorsFilter 403 拦掉,
表现为"页面能打开、一登录就提示网络错误"。同源部署用 http://<部署机IP>:8090
访问同样受影响,一并修复。

- CorsConfig:setAllowedOrigins → setAllowedOriginPatterns,默认放行
http://localhost:*、http://127.0.0.1:*、http://192.168.*:*、http://10.*:*、http://172.*:*
- application.yml / application.yml.example:同步白名单模式与注释
- 白名单校验机制与 allowCredentials=false 未放松,非法来源仍 403
- 新增《功能测试报告_局域网IP访问登录CORS修复_2026-09-16》《工作日结_2026-09-16》
2个文件已修改
2个文件已添加
109 ■■■■■ 已修改文件
docs/功能测试报告/功能测试报告_局域网IP访问登录CORS修复_2026-09-16.md 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/工作日结/工作日结_2026-09-16.md 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/common/config/CorsConfig.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/resources/application.yml.example 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_¾ÖÓòÍøIP·ÃÎʵǼCORSÐÞ¸´_2026-09-16.md
New file
@@ -0,0 +1,53 @@
# åŠŸèƒ½æµ‹è¯•æŠ¥å‘Š_局域网IP访问登录CORS修复_2026-09-16
> æ¨¡å—:系统安全(跨域白名单)+ ç™»å½• 测试人:Codex 日期:2026-09-16
## ä¸€ã€åŠŸèƒ½è¯´æ˜Ž
**问题现象**:用 `http://192.168.177.26:8080/` æ‰“开页面,登录页能正常显示,但点「登录」提示「网络错误,登录失败」;同一套服务用 `http://localhost:8080/` ç™»å½•正常。
**根因**:浏览器对 POST/PUT/DELETE **必带 `Origin` å¤´**(GET ä¸å¸¦ï¼‰ã€‚9-14 å®‰å…¨æ•´æ”¹æŠŠ CORS ä»Ž `allowedOriginPattern("*") + allowCredentials(true)` æ”¶ç´§ä¸ºåªåˆ—具体来源(`http://localhost:8080,http://127.0.0.1:8080`)。经 dev-server ä»£ç†æ—¶ `Origin` åŽŸæ ·è½¬å‘ç»™åŽç«¯ï¼ŒäºŽæ˜¯ `Origin: http://192.168.177.26:8080` å‘½ä¸­ä¸äº†ç™½åå•,`CorsFilter` ç›´æŽ¥è¿”回 403 `Invalid CORS request`(实测报文见用例 C2)。
这解释了"页面正常、一登录就网络错误":页面 HTML/JS ä¸Ž `GET /api/auth/captcha-config` éƒ½ä¸å¸¦ `Origin` å› è€Œä¸å—影响(登录页能显示"测试模式"提示即证明该 GET æˆåŠŸï¼‰ã€‚
**连带风险(本次一并解决)**:打包部署是前端内嵌、与接口同源在 8090,浏览器 POST åŒæ ·ä¼šå¸¦ `Origin: http://<部署机IP>:8090`,用 IP è®¿é—®æ—¶ä¼šåŒæ ·è¢« 403 æŒ¡ä½ç™»å½•。
**改动**(2 ä¸ªæ–‡ä»¶ï¼Œ`CorsConfig.java` / `application.yml`):
- `config.setAllowedOrigins(...)` â†’ `config.setAllowedOriginPatterns(...)`,默认来源放宽为本机 + å†…网网段:`http://localhost:*`、`http://127.0.0.1:*`、`http://192.168.*:*`、`http://10.*:*`、`http://172.*:*`。
- ç™½åå•机制不变(仍是显式来源校验,非通配全放开),`allowCredentials` ä»ä¸º `false`;如改用域名访问,需把域名(含端口)追加到 `app.cors.allowed-origins`(已写入 yml æ³¨é‡Šï¼‰ã€‚
## äºŒã€æµ‹è¯•环境
- åŽç«¯ï¼š8090,改后按 PID ç²¾ç¡®é‡å¯ï¼ˆ`cmd→java(maven)→java(app)`),`Started TrafficAuditApplication` / `Tomcat started on port(s): 8090 (http)`。
- å‰ç«¯ï¼š8080,dev-server æœªé‡å¯ï¼Œé¡µé¢ä¸Žä»£ç†æ²¿ç”¨æœ¬æ¬¡å¯åŠ¨å®žä¾‹ã€‚
- æµè§ˆå™¨ï¼šCodex åº”用内浏览器,`http://192.168.177.26:8080/#/login`(真实浏览器路径,非模拟)。
- å‘½ä»¤è¡Œå¯¹ç…§ï¼š`curl.exe` ç›´å‘同一 URL,用于区分"服务端拒绝"与"浏览器侧失败"。
- è´¦å·ï¼š`admin`(本机库密码 `123456`)。
## ä¸‰ã€ç”¨ä¾‹ä¸Žç»“æžœ
| ç¼–号 | ç”¨ä¾‹ | è¾“å…¥ | é¢„期 | å®žé™… | ç»“论 |
| --- | --- | --- | --- | --- | --- |
| C1 | å¤çŽ°ï¼ˆä¿®å¤å‰ï¼Œæµè§ˆå™¨ï¼‰ | `192.168.177.26:8080/#/login` è¾“å…¥ admin/123456 ç‚¹ç™»å½• | å¤çް"网络错误,登录失败" | é¡µé¢æç¤ºã€Œç½‘络错误,登录失败」,URL åœåœ¨ `#/login` | å¤çŽ°æˆåŠŸ |
| C2 | å¤çŽ°ï¼ˆä¿®å¤å‰ï¼Œå‘½ä»¤è¡Œï¼‰ | POST `/api/auth/login`,带 `Origin: http://192.168.177.26:8080` | èƒ½å®šä½åˆ°æœåŠ¡ç«¯æ‹’ç» | `HTTP/1.1 403 Forbidden` + `Invalid CORS request` | å¤çŽ°æˆåŠŸï¼ˆå®šä½æ ¹å› ï¼‰ |
| C3 | å¯¹ç…§ï¼ˆä¿®å¤å‰ï¼‰ | åŒ C2 ä½†ä¸å¸¦ `Origin` | æ­£å¸¸ | 200 ä¸”返回 token | é€šè¿‡ï¼ˆè¯æ˜Žå·®å¼‚来自 Origin) |
| C4 | ä¿®å¤åŽ LAN æ¥æº | POST `/api/auth/login`,带 `Origin: http://192.168.177.26:8080` | 200 | 200 + token(`管理员`/5 æ¨¡å—) | é€šè¿‡ï¼ˆæ­£å‘) |
| C5 | ä¿®å¤åŽæµè§ˆå™¨å®žç™» | `http://192.168.177.26:8080/#/login` è¾“å…¥ admin/123456 | ç™»å½•成功进工作台 | æç¤ºã€Œç™»å½•成功」,跳转 `#/dashboard`,顶部显示 admin | é€šè¿‡ï¼ˆæ­£å‘,端到端) |
| C6 | æœ¬æœºæ¥æºå›žå½’ | `Origin: http://localhost:8080` | 200 | 200 | é€šè¿‡ï¼ˆæ— å›žå½’) |
| C7 | åŒæºéƒ¨ç½²åœºæ™¯ | ç›´è¿ž 8090,带 `Origin: http://192.168.177.26:8090` | 200 | 200 | é€šè¿‡ï¼ˆæ­£å‘) |
| C8 | å†…网网段来源 | å¸¦ `Origin: http://10.1.2.3:8080` | 200 | 200 | é€šè¿‡ï¼ˆæ­£å‘) |
| C9 | é¢„检请求 | `OPTIONS /api/auth/login` + `Origin: http://192.168.177.26:8080` | 200 ä¸”回显放行来源 | 200,`Access-Control-Allow-Origin: http://192.168.177.26:8080`,方法 `GET,POST,PUT,DELETE,OPTIONS` | é€šè¿‡ |
| C10 | æ—  Origin å¤´ | POST `/api/auth/login`(curl ç›´è¿ž 8090) | ä¸å—影响 | 200 | é€šè¿‡ |
| C11 | éžæ³•来源 | `Origin: http://evil.example.com` | æ‹’绝 | 403 `Invalid CORS request` | é€šè¿‡ï¼ˆè´Ÿå‘,白名单仍生效) |
| C12 | å¸¦ä»¤ç‰Œä¸šåŠ¡æŽ¥å£ | LAN æ¥æº + `Bearer` ä»¤ç‰Œ GET `/api/user/list` | 200 | 200 | é€šè¿‡ |
## å››ã€å‘现的问题与处置
1. **CORS ç™½åå•过窄导致局域网 IP/同源 IP è®¿é—®ç™»å½•失败**(本次主问题):已改为按模式放行本机 + å†…网网段,见上;非法外部来源仍 403。
2. å‰ç«¯ dev æ—¥å¿—显示 `Network: unavailable`(vue-cli æœªæŽ¢æµ‹åˆ°ç½‘卡地址),但 8080 å®žé™…监听 `0.0.0.0`、局域网访问正常(C5 å®žæµ‹ï¼‰ï¼Œå±žæ—¥å¿—提示问题,不处理。
3. ã€Œç½‘络错误,登录失败」这一提示把 403/500 ç­‰æœ‰å“åº”的错误也归到"网络错误",排查时容易误导;`Login.vue` æœªæ”¹åŠ¨ï¼Œåˆ—ä¸ºåŽç»­å¯é€‰ä¼˜åŒ–é¡¹ã€‚
## äº”、结论
局域网 IP(`http://192.168.177.26:8080/`)登录失败问题已修复,命令行走查(C4/C6/C7/C8/C9/C10/C12)与真实浏览器端到端登录(C5)全部通过,白名单负向用例(C11)仍然拦截,未引入鉴权/跨域回归。
docs/¹¤×÷ÈÕ½á/¹¤×÷ÈÕ½á_2026-09-16.md
New file
@@ -0,0 +1,40 @@
# å·¥ä½œæ—¥ç»“_2026-09-16
## ä¸€ã€ä»Šå¤©åšäº†ä»€ä¹ˆ
### 1. çŽ¯å¢ƒå¯åŠ¨
- 11:12 ç”¨ `start-dev.ps1` å¯åŠ¨å‰åŽç«¯ï¼ˆå¯åŠ¨å‰ 8090/8080 å‡ç©ºé—²ï¼‰ã€‚
- å°±ç»ªæ ‡å¿—:后端 `Tomcat started on port(s): 8090` / `Started TrafficAuditApplication`;前端 `Compiled successfully` / `App running at:`。
### 2. ä¿®å¤ã€Œç”¨å±€åŸŸç½‘ IP æ‰“开页面后登录失败」
- **用户反馈**:用 `http://192.168.177.26:8080/` ç™»å½•提示「网络错误,登录失败」,而 `http://localhost:8080/` æ­£å¸¸ã€‚
- **排查路径**:curl ç›´å‘同一 URL çš„ POST `/api/auth/login` æ­£å¸¸è¿”回(说明后端与代理都通)→ ç”¨åº”用内浏览器在 LAN åœ°å€å¤çŽ°ï¼ˆç¡®å®žæç¤ºã€Œç½‘ç»œé”™è¯¯ï¼Œç™»å½•å¤±è´¥ã€ï¼‰â†’ å¯¹æ¯”出差异只在 `Origin` å¤´ â†’ curl è¡¥ `Origin: http://192.168.177.26:8080` å¾—到 `403 Invalid CORS request`,根因落地。
- **根因**:浏览器 POST/PUT/DELETE å¿…带 `Origin`(GET ä¸å¸¦ï¼‰ï¼›9-14 è·¨åŸŸæ”¶ç´§åŽç™½åå•只列了 `localhost:8080 / 127.0.0.1:8080`,经 dev-server ä»£ç†è½¬å‘过来的 `Origin: http://192.168.177.26:8080` å‘½ä¸­ä¸äº†ï¼Œè¢« `CorsFilter` 403 æ‹¦æŽ‰ã€‚页面本身和 `GET /api/auth/captcha-config` ä¸å¸¦ `Origin` æ‰€ä»¥æ­£å¸¸ï¼Œè¡¨çŽ°ä¸º"页面能开、一登录就网络错误"。
- **顺带发现**:打包部署(前端内嵌、用 `http://<部署机IP>:8090` è®¿é—®ï¼‰æ—¶ POST åŒæ ·å¸¦ `Origin: http://<IP>:8090`,也会被 403 æŒ¡ä½ç™»å½•——属于同类隐患,本次一并解决。
- **改动(2 æ–‡ä»¶ï¼‰**:`CorsConfig.java` ç”± `setAllowedOrigins` æ”¹ä¸º `setAllowedOriginPatterns`,默认放行 `http://localhost:*`、`http://127.0.0.1:*`、`http://192.168.*:*`、`http://10.*:*`、`http://172.*:*`;`application.yml` çš„ `app.cors.allowed-origins` åŒæ­¥å¹¶è¡¥æ³¨é‡Šã€‚白名单校验机制与 `allowCredentials=false` å‡æœªæ”¾æ¾ã€‚
- **验证**:按 PID ç²¾ç¡®åœæ—§åŽç«¯é“¾ï¼ˆ`cmd 3608 â†’ java(maven) 23704 â†’ java(app) 12636`)后重启;应用内浏览器在 LAN åœ°å€å®žç™»æˆåŠŸè¿›å…¥ `#/dashboard`;白名单负向用例(`http://evil.example.com`)仍 403。详见《功能测试报告_局域网IP访问登录CORS修复_2026-09-16.md》。
## äºŒã€æµ‹è¯•结果摘要
- CORS ä¿®å¤ 12 æ¡ç”¨ä¾‹å…¨é€šè¿‡ï¼šæ­£å‘(LAN æ¥æºã€åŒæº 8090 æ¥æºã€å†…网网段来源、带令牌业务接口、预检 OPTIONS)、负向(非法来源 403)、回归(localhost æ¥æºã€æ—  Origin å¤´ï¼‰ã€‚
- çœŸå®žæµè§ˆå™¨ç«¯åˆ°ç«¯ï¼š`http://192.168.177.26:8080/#/login` è¾“å…¥ `admin/123456` â†’ æç¤ºã€Œç™»å½•成功」→ è·³è½¬å·¥ä½œå°ï¼Œé¡¶éƒ¨æ˜¾ç¤º admin。
- ä»Šæ—¥æ— å¯¼å…¥/数据库写入操作,未做入库抽查(改动只涉及跨域校验,不触碰数据链路)。
## ä¸‰ã€é—留问题与待办
1. **改用域名访问时需补白名单**:`app.cors.allowed-origins` é»˜è®¤åªè¦†ç›–本机 + å†…网网段,若将来用域名或公网 IP è®¿é—®ï¼Œéœ€æŠŠè¯¥æ¥æºï¼ˆå«ç«¯å£ï¼‰è¿½åŠ è¿›åŽ»ï¼ˆyml æ³¨é‡Šå·²å†™æ˜Žï¼‰ã€‚
2. `Login.vue` æŠŠæ‰€æœ‰å¤±è´¥éƒ½æç¤ºä¸ºã€Œç½‘络错误,登录失败」,403/500 è¿™ç±»æœ‰å“åº”的错误也被归到"网络",排查易误导;建议后续按状态码细分提示(未做,等用户确认)。
3. 9-15 é—留继续挂账:AI å¤–发脱敏补齐(system prompt ä¼ä¸šå/解释原文未脱敏)、保密数据部署路线确认、4 å¼ æ˜Žç»†æŠ¥è¡¨æ¨¡æ¿æ‰©åˆ—、审核比对基准缺失保护、`sys_role` æƒé™è½åœ°ã€3D éªŒè¯ç ç”Ÿäº§å¼€å¯ã€`backend.log` åŽ†å²æ˜Žæ–‡æ¸…ç†ã€‚
4. ä»“库根目录仍有大量未跟踪临时文件(`_*.py`/`_*.sql`/`_*.ps1` ç­‰ï¼‰æœªè¢« `.gitignore` è¦†ç›–,清理前需用户确认。
5. å…¬å¸ gitea(`61.183.254.94:3000`)推送仍受本机凭据问题影响;今日按第 3 æ¡å·¥ä½œè§„范尝试 fetch/合并/推送,结果见下条 git è®°å½•。
## å››ã€æ˜Žå¤©è®¡åˆ’
1. ä¸Žç”¨æˆ·ç¡®è®¤åŸŸå/其他访问方式是否需要一并加白名单,并确认 `Login.vue` é”™è¯¯æç¤ºç»†åˆ†æ–¹æ¡ˆæ˜¯å¦å®žæ–½ã€‚
2. æŽ¨è¿› AI å¤–发脱敏补齐(约 20 è¡Œæ”¹åŠ¨ï¼‰ï¼Œå®ŒæˆåŽå†™ã€ŠåŠŸèƒ½æµ‹è¯•æŠ¥å‘Šã€‹ï¼Œæ²¿ç”¨"假 DeepSeek æœåŠ¡æŠ“åŒ…"做报文级验证。
3. ç»§ç»­æŽ¨è¿›æŠ¥è¡¨æ¨¡æ¿æ‰©åˆ— / å®¡æ ¸åŸºå‡†ä¿æŠ¤ç­‰æŒ‚账项。
## äº”、git è®°å½•
- æœ¬æ¬¡æ”¹åŠ¨ï¼š`CorsConfig.java`、`application.yml`、本报告与日本日结。
- æµç¨‹ï¼šå…ˆå†™ã€ŠåŠŸèƒ½æµ‹è¯•æŠ¥å‘Šã€‹ä¸Žæœ¬ã€Šå·¥ä½œæ—¥ç»“ã€‹ï¼Œå† `git fetch origin`(gitee,`master`)与 `git fetch gitea`(公司,`main`)对比合并,确认无冲突后提交并推送。
traffic-audit-server/src/main/java/com/trafficaudit/common/config/CorsConfig.java
@@ -12,14 +12,16 @@
import java.util.List;
/**
 * è·¨åŸŸé…ç½®ï¼šåªå…è®¸é…ç½®ä¸­åˆ—出的来源访问接口。
 * å‰åŽç«¯åˆ†ç¦»æœ¬åœ°å¼€å‘默认放行 8080;前端经 dev-server ä»£ç†æˆ–与后端同源部署时均不需要额外放行。
 * è·¨åŸŸé…ç½®ï¼šåªå…è®¸é…ç½®ä¸­åˆ—出的来源(支持 * é€šé…ï¼‰è®¿é—®æŽ¥å£ã€‚
 * æµè§ˆå™¨å‘èµ· POST/PUT/DELETE æ—¶ä¼šå¸¦ Origin å¤´ï¼ˆGET ä¸å¸¦ï¼‰ï¼Œå› æ­¤ç”¨å±€åŸŸç½‘ IP æ‰“开页面时,
 * è‹¥è¯¥æ¥æºä¸åœ¨æ”¾è¡Œåˆ—表内会被 CorsFilter åˆ¤ä¸ºéžæ³•并返回 403,表现为登录时提示“网络错误”。
 * é»˜è®¤æ”¾è¡Œæœ¬æœºä¸Žå†…网网段的任意端口(本地开发、局域网访问、IP æ–¹å¼è®¿é—® 8090 åŒæºéƒ¨ç½²éƒ½è¦†ç›–)。
 * æ³¨æ„ï¼šä¸å¼€å¯ allowCredentials(接口用 Bearer ä»¤ç‰Œé‰´æƒï¼Œä¸ä¾èµ– Cookie),避免任意站点携带凭证调用。
 */
@Configuration
public class CorsConfig {
    @Value("${app.cors.allowed-origins:http://localhost:8080,http://127.0.0.1:8080}")
    @Value("${app.cors.allowed-origins:http://localhost:*,http://127.0.0.1:*,http://192.168.*:*,http://10.*:*,http://172.*:*}")
    private String allowedOrigins;
    private List<String> originList() {
@@ -29,7 +31,7 @@
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(originList());
        config.setAllowedOriginPatterns(originList());
        config.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type", "Accept", "X-Requested-With"));
        config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        config.setAllowCredentials(false);
traffic-audit-server/src/main/resources/application.yml.example
@@ -70,7 +70,9 @@
# Behavior captcha on login. Set to false to skip verification during test phase; enable before production release.
app:
  cors:
    # å…è®¸è·¨åŸŸè®¿é—®æŽ¥å£çš„æ¥æºï¼ˆé€—号分隔)
    allowed-origins: http://localhost:8080,http://127.0.0.1:8080
    # å…è®¸è·¨åŸŸè®¿é—®æŽ¥å£çš„æ¥æºï¼ˆé€—号分隔,支持 * é€šé…ä¸»æœºä¸Žç«¯å£ï¼‰ï¼š
    # æµè§ˆå™¨ POST/PUT/DELETE å¿…带 Origin(GET ä¸å¸¦ï¼‰ï¼Œæ•…用 IP/域名打开页面时该来源必须命中此列表,否则 403。
    # é»˜è®¤æ”¾è¡Œæœ¬æœºä¸Žå†…网网段;若通过域名访问,请把该域名(含端口)追加到此处。
    allowed-origins: http://localhost:*,http://127.0.0.1:*,http://192.168.*:*,http://10.*:*,http://172.*:*
  captcha:
    required: false