跳转到内容

KEC 微信小程序端 可行性评估报告

评估日期:2026-08-09 | 评估对象:kec-manager v1.0.2 约束条件:不改动现有 Web 前端与后端逻辑;目标产物为小程序体验版(不追求正式上线)


〇、总体结论

方案可行,且比预想的顺利——现有后端在"非浏览器客户端"场景下的兼容性意外地好,核心链路已实测跑通,无需改动一行后端代码

但有 3 个门槛必须提前知道:

#门槛能否绕过严重度
1CSRF 双提交:所有写请求(含登录)强制要求 Cookie + Header 同时携带可绕,但依赖小程序 cookie 行为,需先做 PoC🔴 决定成败
2服务器域名:体验版强制校验 HTTPS + ICP 备案域名真机"打开调试"可临时绕过🟡 影响体验
3功能范围:现有 20 个主页面是重表格 + 弹窗形态必须裁剪,不能照搬🟡 影响工期

关于你担心的"教育类可能无法上线"——在"仅做体验版"这个目标下,这个担心基本不成立。体验版不走审核流程,类目资质与 ICP 备案只影响正式上架。详见第三节。


一、后端兼容性实测(已本地跑通)

我起了本地服务(:3002),用 curl 模拟小程序的请求特征(不发 Origin、纯 Header 认证)逐项验证:

能力结论依据
CORS✅ 零改动app.js:76 对无 Origin 请求直接放行(注释明确写了"移动端等非浏览器客户端")。小程序 wx.request 不发 Origin
Bearer 认证✅ 零改动auth.middleware.js:66 优先读 Authorization: Bearer,Cookie 只是备选。实测纯 Bearer 零 Cookie 成功拉到数据
登录返回值✅ 零改动响应体直出 token / refreshToken / csrfToken不需要读 Cookie 就能拿全所有凭据
Token 续期✅ 零改动auth.routes.js:181 支持 req.body.refresh_token;小程序发 camelCase 的 refreshToken,命名中间件自动转 snake_case。实测换票成功
命名风格✅ 零改动convertRequestNaming / convertResponseNaming 全局生效,小程序端与 Vue 端一样全程写 camelCase
CSRF 校验⚠️ 唯一卡点见下节

实测记录

bash
# 步骤1:GET /api/auth/csrf-token
# → 响应体直接返回 {"csrfToken":"8d8926..."},同时 Set-Cookie: XSRF-TOKEN=8d8926...; SameSite=Strict

# 测试A:POST /api/auth/login,只带 X-CSRF-Token 头,不带 Cookie
{"success":false,"message":"CSRF验证失败,请刷新页面后重试"}      # ❌ 403

# 测试B:POST /api/auth/login,Header + Cookie 都带
{"success":true,"data":{"user":{...},"token":"eyJ...","refreshToken":"eyJ..."}}   # ✅

# 测试C:纯 Bearer 读数据,零 Cookie
GET /api/query/semester   → ✅ 216 个班级,字段已自动转 camelCase
GET /api/teachers         → ✅ 正常分页返回
GET /api/dashboard/stats  → ⚠️ {"success":false,"message":"请选择学期"}(需带 semester 参数,非阻塞)

# 测试D:POST /api/auth/refresh,body 传 camelCase refreshToken
{"success":true,"data":{"token":"eyJ..."}}                        # ✅ 命名中间件自动转换生效

结论:读操作(GET)完全无障碍;写操作(含登录)卡在 CSRF。


二、CSRF 卡点分析(决定成败的关键)

问题本质

validateCsrfapp.js:137)是全局中间件,对所有 POST/PUT/DELETE 强制要求:

  1. Header X-CSRF-Token 与 Cookie XSRF-TOKEN 同时存在且值相等(Double Submit)
  2. 该 token 的 HMAC 签名有效

/api/auth/login 也在其管辖范围内 —— 也就是说,小程序若无法携带 Cookie,连登录都进不去,整个方案卡死在第一步。

小程序侧的不确定性

微信 wx.request 的 Cookie 行为在官方文档中没有明确承诺,社区反馈存在矛盾:

  • 一说微信有全局 Cookie 容器,会自动存 Set-Cookie 并在同域请求自动回带(多数项目按此实践)
  • 一说小程序"阉割"了自动 Cookie,必须手动从 res.header['Set-Cookie'] 提取再手动注入
  • 还有反馈称手动设置 header 的 Cookie 字段会被客户端覆盖或忽略,且 iOS / Android / 开发者工具三端行为不一致

叠加后端 Cookie 带了 SameSite=Strict,微信客户端如何处理该属性也无保证。

这一条必须用 15 分钟的 PoC 先验证,不要在没验证前动手写业务代码。 PoC 内容:小程序里 GET /api/auth/csrf-token → 拿响应体的 csrfToken → POST /api/auth/login 同时塞 Header 和 Cookie → 看能否登录成功。需在开发者工具 + iOS 真机 + Android 真机三端各跑一次。

三种应对方案

方案做法改动范围评价
A. 直连(PoC 通过时)小程序封装 request,自动维护 csrfToken,写请求时同时注入 Header 与 Cookie零改动,纯新增小程序目录⭐ 首选。最轻,符合约束
B. 纯只读(PoC 失败的兜底)小程序只做查询展示,写操作全部不做;登录改用……问题是登录本身就是 POST零改动,但登录也是 POST,仍卡❌ 不成立,除非配合 C
C. Nginx 注入(最稳)反向代理开一个 /mp-api/ 路径,在 Nginx 层根据 X-CSRF-Token 头自动补 Cookie: XSRF-TOKEN=同值不改代码,只改运维配置⭐ 强烈推荐作为保险。3 行 proxy_set_header 搞定
D. BFF 中间层新起一个 Node 小服务持 cookie jar 转发不改现有代码,但多一个进程🔧 最重,非必要不上

建议路线:先做 A 的 PoC,失败则上 C。 C 方案本质上只是在代理层补一个 Header,不触碰任何业务逻辑,完全符合"不改动现有项目"的约束。


三、微信平台侧门槛

3.1 服务器域名(真正的拦路虎)

体验版运行在生产级安全沙箱中,强制校验:

  • 域名已在小程序后台「开发管理 → 服务器域名」配置(不含协议、端口、路径)
  • 域名已完成 ICP 备案
  • 有效 HTTPS 证书(非自签、含完整信任链)、TLS 1.2+
  • ⚠️ 不支持非 443 端口的特殊端口要谨慎,目前部署是 3000:3000,必须走 Nginx 反代到 443

唯一的免费出路:真机扫码打开体验版后,点右上角「···」→「打开调试」,可临时跳过域名校验。 代价是每个体验用户每次都要手动开调试,且这个开关会随小程序重启失效——内部小范围演示够用,给领导演示会很尴尬

如果学校/单位已有备案域名(看部署脚本走的是 1Panel /opt/www/sites/kec/,很可能已经有),那这一条直接消失,配个二级域名即可。

3.2 类目与审核(你担心的点,实际影响很小)

事项对体验版的影响
教育类目资质(办学许可证等)无影响。体验版不提交审核
小程序 ICP 备案无影响。仅影响正式上架(未备案上架会限 50 用户/天、搜不到、90 天内不备案则下架)
服务类目选择注册时要选,但本项目是校内教务管理工具,不是 C 端在线教育,可选「工具 → 效率」或「IT科技 → 软件服务」,完全避开教育类资质要求

所以"因涉及教育类可能无法上线"这个前提,其实是可以被绕开的 —— 只要产品定位讲清楚是内部管理工具而非面向学生招生/授课,正式上线也未必没戏。当然,先做体验版是稳妥的。

3.3 体验成员数量上限

主体类型项目成员体验成员
个人1515
企业/组织(未认证/已认证/已发布)2030 / 60 / 90

校内教务小范围使用,个人主体的 15 人通常够;如果要给全院老师用,需要企业主体。

3.4 其他平台限制(开发时要注意)

  • wx.request 并发上限 5,第 6 个请求静默挂起 → 首页别一口气打 8 个接口
  • 后端限流 120 次/分钟/IPapp.js:114),生产环境生效,多人同时用要留意
  • 主包 ≤ 2MB,总包 ≤ 20MB —— 对纯查询类小程序绰绰有余
  • timeout 只接受 1000–60000ms

四、工作量评估与功能裁剪建议

现状规模

  • 45 个 .vue 文件(约 20 个主页面 + 25 个子组件/弹窗)
  • 19 个通用组件、17 个 API 模块、3 个 store
  • Element Plus 重表格 + 多层弹窗 + 排课算法交互(TeachingArrange 一个页面就带 10 个子组件)

照搬是错的

管理后台的「大宽表 + 多列筛选 + 批量操作 + 模态弹窗」范式在 375px 宽的手机上基本不可用。建议按「小程序做查询、Web 做管理」分工:

模块是否移植理由
登录 / 改密✅ 必做入口
Dashboard 概览✅ 推荐卡片式,天然适配手机
学期开课查询✅ 推荐高频只读,移动端价值最大
教材使用查询✅ 推荐同上
教师课时查询/统计✅ 推荐老师自查周课时,移动端刚需
班级/课程/专业 列表查询🟡 可选只读列表 + 搜索
教学安排(排课)❌ 不建议10 个子组件、算法交互、长时任务,手机上做不了也不该做
导入 / 导出❌ 不建议Excel 上传下载在小程序上体验很差
系统设置 / 用户管理 / 审计日志❌ 不建议低频管理操作,留在 Web 端

推荐 MVP

6 个页面、纯只读 + 登录:登录 → 首页概览 → 开课查询 → 教材查询 → 教师课时 → 我的信息。

这样做还有一个额外好处:除登录外全是 GET,CSRF 卡点只剩登录一处,风险面收敛到最小。

技术选型建议

选项评价
原生小程序 + TDesign MiniProgram⭐ 推荐。包体最小、启动最快、无构建链路负担,TDesign 组件齐全且是腾讯官方出品
uni-app / Taro生态熟悉可用,但为 6 个页面引入完整构建链不划算

目录建议放在项目根下新建 miniprogram/,与 client/ server/ 平级,不侵入现有任何目录


五、风险清单

风险等级应对
小程序无法携带 Cookie → 登录失败🔴 高先做 PoC;失败则用 Nginx 注入 Cookie(方案 C)
无备案域名 → 体验版必须开调试才能用🟡 中确认单位是否已有备案域名;否则接受"开调试"的临时方案
后端 SameSite=Strict 在微信客户端行为未知🟡 中PoC 时一并验证
15 分钟 access token 过期 → 频繁续期🟢 低封装 request 时做 401 自动 refresh 重试(Web 端已有同款逻辑可参考)
强制改密(MUST_CHANGE_PASSWORD 403)🟢 低小程序端识别该 code,引导跳改密页
生产限流 120/min🟢 低首页接口合并、加缓存
导出 Excel 在小程序端🟢 低MVP 不做;后续可用下载票据 + wx.downloadFile + wx.openDocument

六、建议的下一步

第 1 步(0.5 天):PoC 验证——只写 1 个页面,验证 3 件事:

  1. 小程序能否完成登录(Cookie 能否带上)
  2. 纯 Bearer 能否拉到 /api/query/semester 数据
  3. 401 后 refresh 能否自动续期

PoC 通过 → 后续开发基本无技术风险。PoC 不通过 → 加一层 Nginx 配置,再通。

第 2 步(2-3 天):MVP 6 个页面——原生小程序 + TDesign,只读为主。

第 3 步:真机验证 + 体验版发布——需要你提供:小程序 AppID、后端公网 HTTPS 地址。


附:需要你确认的信息

  1. 是否已有已备案的 HTTPS 域名指向后端?(决定体验版是否必须开调试模式)
  2. 小程序账号的主体类型?(个人 15 人 / 企业最多 90 人体验成员)
  3. MVP 功能范围是否认可上面的 6 页方案?有没有必须加的模块?
  4. 是否接受在 Nginx 层加配置(不改代码)作为 CSRF 的兜底方案?