Files
pj_service_cloud/docs/file-access/verification.md
T
dzc bbde6cc87f fix:图片访问
fix:权限修改
2026-10-29 14:28:38 +08:00

11 KiB
Raw Blame History

五端文件签名验证记录

验证日期:2026-10-29。范围为本地五个项目的实现、定向回归、构建和已登录后台页面检查。未发布服务、修改 Nacos、开启生产拦截、更新真实设备、执行数据库迁移或提交 Git。

已完成

验证 结果
Java 请求级与业务回归 41 项通过,0 失败;覆盖 UPMS 文件校验/读取、版本地址、钱包和硬件导出,同时编译相关公共模块及 canteen
后台自动测试 14 项通过,包含文件协议与已有部门导出测试
H5 文件自动测试 14 项通过
小程序文件自动测试 14 项通过
跨语言协议 Java、三端 TypeScript、Dart 使用相同公开向量;校验 UTF-8 文件名、秒级时间戳、Base64URL 原文和 HMAC 结果
URL 与运行时 覆盖中文、空格、加号、百分号编码、历史域名、相对/绝对地址、已有 /api 前缀、重复签名、第三方地址;前端测试执行实际运行时包装器,H5/小程序测试执行富文本预览组件的 JS 方法;Java 使用真实 SpringMvcContract/Feign 客户端与内存传输验证文件名字面 %2F/%2B、重复拦截和参数顺序
后台生产构建 pnpm build:prod 通过
H5 构建 pnpm build:h5 通过
微信小程序构建 pnpm build:mp-weixin 通过
Flutter 定向回归 56 项通过;含签名、安装包一次重试、人脸同步计划/流水线/失败记录/缓存、主副屏余额回归
Android Release FVM Flutter 3.27.4 构建通过,使用 .file-access/production.json;APK 约 101.9 MB
新增后台 TypeScript 工具 独立严格类型检查通过
配置生成器 在临时目录重复运行,确认幂等、保留已有文件;开发/测试/生产配置和各客户端密钥相互独立
密钥与原有变更 扫描五个项目全部已跟踪及未忽略候选文件,未发现生成密钥泄漏;后台原有补丁可反向校验,Java 原有补丁除追加忽略规则产生的上下文差异外可反向校验
Diff 检查 保留原有 CRLF 文件格式;使用 git -c core.whitespace=cr-at-eol diff --check 通过

APK 位置(相对本仓库):../pj_supermarket_cloud/build/app/outputs/flutter-apk/app-release.apk。本次构建尚未在真实终端安装验证;发布前须核对包内环境与服务端配置一致。

Java 定向测试及各端构建命令见 接入与发布说明。本机详细日志保存在 /tmp/pj-file-access-work/,属于临时验证资料,不随仓库发布。

静态检查与既有问题

使用任务开始前保存的补丁还原临时代码基线,与当前代码运行同一检查后比较:

项目 当前结果与基线比较
后台 vue-tsc 6 条既有解析错误,均在 src/views/admin/system/tenant/index.vue:83;与基线完全一致
H5 vue-tsc 4 条既有解析错误,在 src/pages/tabbar/~individualOrder.vue:78-79;与基线完全一致
小程序 vue-tsc 17 条既有 TS6504(JS Vue 来源与 allowJs 配置);规范化临时目录路径后与基线完全一致
Flutter analyze --no-pub 69 条提示/警告;忽略因新增代码产生的行号偏移后,诊断集合与基线完全一致,无新增项

因此不能把本次结果表述为“全项目类型检查通过”。H5/小程序构建仍有 TM UI 类型导出和循环依赖等构建提示;构建已成功,未在本次跨端文件改造中整理无关依赖。

已登录后台检查

使用用户提供的 http://localhost:8888/ 已登录会话,检查文件管理页:

  • 本系统有效图片的缩略图与放大预览加载成功,资源请求带 appId/kid/ts/sign,fileName 位于最后。
  • 实测发现并修复前端 /api 前缀被重复保留的问题:当前开发图片服务器不带 /api,相对旧路径应转换为 /admin/sys-file/oss/file。配置含 /api 的部署仍保留一次前缀。
  • 旧头像的一条原始文件链接返回 HTTP 200、内容长度为 0,属于当前运行后端/存储的既有异常。新 Java 读取代码已覆盖不存在和存储异常状态,但尚未发布,不能声称现场问题已修复。
  • 当前后端匿名 /admin/sys-file/oss/access-info 返回 424 鉴权错误,说明运行环境尚未具备本次匿名校时接口;签名客户端会保留本地时间/最近偏移,不降级匿名读取。
  • 点击素材下载后未出现页面错误,但浏览器下载事件未在等待窗口内返回。浏览器工具自动安全检查拒绝打开 chrome://downloads/(仅允许 HTTP/HTTPS),未采用其他方式绕过此限制,下载文件实际落盘未确认。

当前运行后端仍接受裸文件链接。上述浏览器结果证明前端签名与展示链路可用,不代表新后端严格校验已在线生效。

发布前仍需完成

  1. 核对每个环境的公网基础地址、历史域名、密钥和活动 kid;Java 不会自动加载 .file-access/*.yml,须通过 Nacos 或 SPRING_CONFIG_ADDITIONAL_LOCATION 加载。先以 observe 发布 UPMS、integrated 和所有实际调用文件服务的模块。
  2. 用发布后的后端确认匿名校时可达,执行 GET/HEAD、错误参数、错误/过期签名、旧 Dart 兼容、404/500、私有缓存及服务间读取联调。
  3. 在真实旧 Flutter 安装包上确认图片请求 UA、图片显示及 Android 原生 APK 下载。新版包确认主副屏、缓存命中、人脸重复同步/离线恢复、取证、打印、手动/自动更新;不能用本地源码或单元测试替代设备验收。
  4. 微信真机验证登录前 Logo/背景、长时间停留和恢复前台、图片预览、文件下载及打开文档;核对微信文件域名配置。后台与 H5 补充对应实际业务操作验收。
  5. 至少观察一个完整业务日,确认已知入口无遗漏后再切 enforce;根据设备版本台账确认升级覆盖后再关闭旧 Dart 图片兼容。

当前默认保持 observe 与旧 Dart 图片兼容开启。回滚方法是恢复 observe 并保留诊断日志;业务引用和人脸记录未持久化临时签名,无需数据库回滚。

后台图片闪烁修复补充

2026-10-29 修复后台单张图片失败重试清空全局签名缓存的问题。重试只刷新当前文件,同一文件的并发重试合并;普通校时保留仍有效的签名。新增公共 FileImage,已加载图片在分钟检查、签名续期和恢复前台时保持当前画面;未加载的懒图片继续更新有效地址,放大预览在打开或切换图片时取有效签名。业务引用改变时正常加载新图。

  • 后台定向回归 19 项通过,包含真实组件 setup、模板与 Vue 生命周期测试;模拟停留超过 30 分钟、恢复前台、失败重试、预览和懒加载。
  • 新组件与文件工具的定向 vue-tsc 检查通过;后台生产构建通过。
  • 已登录商户页实测:原先已加载的 24 张图片跨分钟检查后地址不变,其余慢图片随后加载完成,共 30 张图片成功、无加载占位;放大预览成功且请求带签名。

浏览器直接打开文件地址限制补充

2026-10-29 新增默认开启的 block-browser-navigation。严格模式下,携带浏览器页面导航 Fetch Metadata 的文件请求,即使签名有效也返回 403;页面图片、音视频、fetch/XHR 下载和无浏览器 Metadata 的原生/服务请求继续按原签名规则处理。成功响应 Vary 区分导航与子资源请求;拒绝响应 no-store。观察模式仅记录 browser_navigation。

  • Java 文件访问/读取请求级测试共 12 项通过,覆盖签名正确的导航、GET/HEAD 在读取存储前拒绝、图片与下载放行、原生包下载、Dart UA 不绕过导航限制、开关和观察模式。
  • 后台 20 项、H5 16 项、小程序 16 项定向测试通过。覆盖文件链接的页面内下载、H5 富文本与普通链接拦截、图片预览、本地文档打开及第三方链接保持原行为。
  • 后台生产、H5、微信小程序构建通过;后台文件组件/工具定向类型检查通过。
  • 配置生成器在临时目录验证:新配置含 block-browser-navigation: true,默认仍为 observe,没有修改实际运行环境配置。

这项补充尚未部署到文件服务器,不能把本地请求级测试表述为该公网地址已返回 403。上线时代理须保留 Sec-Fetch-Mode/Dest 和响应 Vary;用新签名或无旧缓存的窗口验证。后端无法收回浏览器已经取得的文件内容。旧浏览器可能不提供 Fetch Metadata,脚本也能模拟请求,因此这项规则不等于逐用户授权或防止已显示图片被保存。

最终调整:统一一套密钥与严格模式联调

用户明确要求所有环境使用同一套密钥,取代本文前面记录的开发/测试/生产独立密钥方案。沿用已配置的原生产密钥组,未生成新密钥;各 appId 仍使用各自固定密钥,service/package 密钥仍只存在服务端。三个前端统一使用 .env.local,Java 使用 .file-access/config.yml,Flutter 使用 .file-access/config.json。旧模式文件的签名字段已清理并备份,旧命令 --environment 不再切换密钥。

此前严格模式白图的真实原因是:浏览器按开发密钥签名,后端配置的是原生产密钥,实际响应为 invalid_signature。本次已通过本地 Nacos REST API 修正 application-dev.yml,保留 enforce、浏览器导航拦截和旧 Dart 兼容,公网基础地址对齐测试网关。Nacos 完整原配置保存在本机私有临时备份,发布时使用 MD5 比较避免覆盖并发编辑,生产服务配置未修改。

  • 使用真实页面中的同一个签名 URL 联调:页面图片请求 200、应用下载请求 200、浏览器导航请求 403,原因为 browser_navigation。
  • 实际后台重新加载后,首轮观察为 30 张图片中的 24 张加载成功,其余 6 张仍在慢请求中;随后浏览器自动化连接中断,未把该轮全部图片的最终状态作为已验证结果。签名已与统一密钥注册表一致。
  • 真实 Vite loadEnv 验证三个项目共 18 个模式组合,全部使用统一密钥;生成器迁移、重复执行、原密钥保留与错误配置拒绝共 3 项测试通过。
  • 后台生产、H5、微信小程序构建通过;Flutter 使用统一配置执行签名和安装包定向测试,8 项通过。

后续构建与配置准备以 README 中的统一路径为准。本文前面提到的分环境配置路径属于历史验证记录,不再作为当前操作指引。