“完整”指 vendor/ 与 composer.lock 中 dist.sha256 严格一致;verify-checksums --strict 是唯一真校验命令,需 COMPOSER_EXPERIMENTAL=1 启用,它逐包计算 SHA256 并比对,跳过无 dist.sha256 的包,不校验生成文件,生产环境须设 vendor/ 只读并断言 autoload.php 未被篡改。

Composer 安装“完整”不等于 composer install 没报错——它只说明下载解压流程走通了,不代表 vendor/ 里的文件没被篡改、没被镜像污染、也没跳过校验。真正能回答“是否完整”的,只有比对当前 vendor/ 内容与 composer.lock 中记录的 dist.sha256 是否一致。
verify-checksums 是唯一能真读磁盘比哈希的命令,但默认不启用
这个命令从 Composer 2.5 起存在,但属于实验功能,必须显式开启环境变量才能用:
-
COMPOSER_EXPERIMENTAL=1 composer verify-checksums --strict是唯一能逐包读取vendor/目录、计算实际文件 SHA256、并与composer.lock中dist.sha256字段比对的机制 - 不加
--strict时,哪怕发现不匹配也只警告并返回 0,CI 流水线会误判为成功 - 它不会出现在
composer list默认输出里,不设COMPOSER_EXPERIMENTAL=1就根本看不到这个命令 - 它跳过
type: "path"或没有dist.sha256字段的包(比如老旧私有包),但不会报错,容易漏检
为什么 composer install 成功后,verify-checksums 却失败?
因为两者校验时机和对象完全不同:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
composer install只在校验刚下载的 zip/tar 包(解压前)是否匹配composer.lock中的dist.sha256;一旦解压落地,就不再回头检查 -
verify-checksums是真打开vendor/目录,递归读所有文件(排除.git、tests/等非发布路径),归并字节流再算一次 SHA256 - 常见触发失败的场景:手动改过
vendor/autoload.php(它不在生成文件列表里,但会被verify-checksums扫到)、CI 构建中用了--prefer-source、或本地缓存被污染后重装却复用了坏包 - 注意:
verify-checksums不校验vendor/composer/autoload_*.php这类生成文件,只校验原始 dist 包发布的结构
手动定位单个包哈希不一致,别信模糊报错
verify-checksums 报 Checksum mismatch 却不指明哪个文件?这是设计使然——它只做包级比对,不深入到单个 PHP 文件。要快速定位,得自己动手:
- 先用
composer show --locked vendor/package --format=json提取该包的dist.sha256值 - 进
vendor/vendor/package目录,运行:find . -type f ! -name '.git*' ! -path './tests/*' -print0 | sort -z | xargs -0 shasum -a 256 | shasum -a 256 - 对比两次结果:若不一致,说明该包目录内有文件被增删或修改(比如多了调试文件、删了 LICENSE、或注入了恶意代码)
- 别直接跑
shasum -a 256 .—— 目录本身不可哈希,必须先归并所有文件内容再算
中文路径或文件名不影响 SHA256 计算,但要注意编码一致性
SHA256 是对字节流哈希,不是对字符串。只要文件内容字节完全一致,无论文件名是中文、emoji 还是 emoji + 中文混合,哈希值都相同。但实操中容易踩坑:
- 某些编辑器保存中文文件名时可能自动转成 UTF-8 或 GBK 编码,导致
find列出的路径字节不同,最终哈希不一致 - Git 在 Windows 上默认启用 core.autocrlf,可能悄悄转换换行符,改变文件字节流
- 如果项目里混用不同 locale 的构建机(如 CI 节点是 en_US.UTF-8,本地是 zh_CN.UTF-8),建议统一设置
export LC_ALL=C再跑哈希计算,避免排序或通配行为差异 - 验证时优先用
composer show --installed --format=json和composer show --locked --format=json对比dist-sha256字段,绕过文件系统层干扰
最常被忽略的一点:vendor/autoload.php 被替换成 eval($_GET['x']) 后,所有上述命令都不会报警——它既不在 composer.lock 的哈希覆盖范围,也不在 verify-checksums 的校验清单里。生产环境必须设为只读:chmod -R a-w vendor/,CI 中加一行 grep -q "autoload_real\.php" vendor/autoload.php || exit 1 断言入口未被篡改。

















