恢复点(restore point)。别人改崩后可 git reset --hard 回到此提交。 == 此快照内容 == - 后端 oa-backend: 734 控制器 / 711 实体 (Spring Boot 3.2.5 + SQLite, 端口8091) - 前端 modern-ui/app: Vue3+Vite, 约700页 (构建产物已在 oa-backend/src/main/resources/static) - 数据库 oa-backend/data/oa.db: 含全部演示数据 (强制入库, 6.6MB) - 交接文档 go.md + go-code-reference/endpoints/entities/database.md - 多代理建设脚本 .claude/wf-*.js == 状态 == - 对 凯迪科技ERP_20260507.xlsx 合规 MET ~73.3% (PARTIAL 75: 34可建+6种子/bug+35外部硬天花板) - 安全: 5轮红队+5轮复检, default-deny分级鉴权, 连续零可利用 - W3~W7 累计补完436缺口; W8末轮(40缺口)为半成品(源码树可编译但未集成) - 运行: cd oa-backend; java -jar build/libs/oa-backend-0.1.0.jar --server.port=8091; admin/123456 == 排除(gitignore, 可再生) == node_modules / oa-backend/build / .jdks / *.log / Backup-ERP-* / 弃用的OFBiz核心(只保留modern-ui) 完整文件夹备份见同目录 Backup-ERP-20260615-191517/ (含上述全部, 仅缺 node_modules) 时间戳: 20260615-191517 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3.2 KiB
3.2 KiB
OA Backend — Security Audit
Audit of the standalone Java (Spring Boot) OA backend after functional tests
reached 100% (42/42, see ../oa-itest.sh). Scope: injection, XSS, secrets,
authn/authz, transport, CORS, password storage.
Summary
| Class | Status | Notes |
|---|---|---|
| SQL injection | Safe | All persistence via Spring Data derived queries (parameterized). No @Query, no createQuery, no native SQL, no string-concatenated queries anywhere. |
| XSS (stored/reflected) | Safe | Frontend has zero v-html / innerHTML / eval / new Function. Vue + Element Plus escape all interpolated text by default. Form/flow JSON is rendered as data, never as HTML. |
| Hardcoded secrets | Safe | No API keys, tokens, or secrets embedded in source. |
| Mass assignment | Safe | Controllers bind explicit record DTOs, never JPA entities directly. |
| Password storage | Hardened | Upgraded from unsalted SHA-256 to salted PBKDF2-HMAC-SHA256 (120k iterations, per-user 16-byte salt), constant-time verify. See common/PasswordUtil. |
| Error handling | Safe | Uniform ApiResp envelope via @RestControllerAdvice; no stack traces leaked to clients. |
| Transport (CORS) | Dev-scoped | /api/** allows localhost:* / 127.0.0.1:* only — appropriate for local dev; must be locked to the real origin for production. |
Remaining hardening (documented as "later phase", acceptable for the current single-tenant demo)
- Token lifecycle — opaque in-memory bearer tokens with no expiry and no persistence across restarts. For production: signed/JWT or server-side sessions with TTL + refresh + revocation list.
- Authorization enforcement — most endpoints don't require a valid token;
an unauthenticated caller falls back to the demo user
我(当前用户). This is intentional so the demo runs without a login gate. For production: a filter that rejects unauthenticated/under-privileged calls on mutating routes, plus RBAC using the existingSysRole/SysUserRoletables. - Rate limiting / lockout — no brute-force protection on
/auth/login. Add attempt throttling + temporary lockout. - HTTPS — served over plain HTTP on :8090 for local dev; terminate TLS at a reverse proxy (or enable Spring SSL) in production.
- CORS lockdown — replace the
localhost:*dev pattern with the deployed frontend origin(s). - Audit log — workflow actions are traced (
FlowTrace), but there is no security/access audit log; add one for production compliance.
What was fixed in this pass
common/PasswordUtilrewritten to salted PBKDF2 (was unsalted SHA-256), with a legacy-hash fallback inmatches()for backward compatibility. Re-seeded users now storepbkdf2$<iter>$<salt>$<hash>. Verified: loginadmin/123456→ success; wrong password → 401.- CORS origin patterns documented and scoped (see
config/CorsConfig).
Verdict
No exploitable vulnerabilities found in the audited classes (injection, XSS, secrets, mass-assignment). Password storage is now industry-standard salted KDF. The remaining items are deployment-hardening tasks expected of a demo moving to production, all tracked above.