composer install 不报错但依赖不对,是因为它仅依赖 composer.lock 文件存在且格式合法,不校验 vendor 中包内容与 lock 中哈希值是否一致;--dry-run 是唯一能真实校验二者一致性的方法。

composer install 时为什么没报错,但依赖却不对
因为 composer install 默认只检查 composer.lock 文件是否存在和格式是否合法,并不校验其中哈希值与实际已安装包内容是否一致。只要 lock 文件能解析,它就照着装,哪怕 vendor 里某个包被手动改过、删过,或从别处复制过来,它也默认“信任 lock”。
用 composer validate --strict 校验 lock 文件结构
这个命令只检查 composer.lock 的 JSON 结构、字段完整性、schema 兼容性,比如是否有缺失的 content-hash 字段、package 名是否含非法字符等。它**不验证文件内容真实性**。
-
composer validate --strict会提示lock file is not up to date—— 这其实是说composer.json修改后未运行composer update或composer install生成新 lock,不是内容被篡改 - 它不会读取
vendor/下任何文件,也不比对 checksum - CI 中常用它做基础门禁,但防不了依赖投毒或本地误改
真正校验 lock 文件与 vendor 一致性:composer install --dry-run
这是最贴近“校验数据真实性”的实操方式。composer install --dry-run 会模拟安装流程:解析 composer.lock → 计算每个包预期的 dist.sha256 或 source.reference → 检查 vendor/ 中对应目录是否存在、是否匹配哈希(如果 lock 里有完整 checksum)→ 报出差异。
- 必须确保当前没有
composer.lock被修改且未提交,否则 --dry-run 可能触发重写 lock - 若 lock 中 package 条目缺少
dist.sha256(老版本 Composer 生成),则跳过该包的哈希校验,仅检查路径存在性 - 输出中出现
Would install ...表示一致;出现Would remove ...或Would update ...就说明 vendor 和 lock 不符
手动比对关键哈希:看 content-hash 和 vendor 哈希是否匹配
composer.lock 顶部的 content-hash 是对 composer.json 内容做的 hash,**和 vendor 无关**;真正关联 vendor 的是每个 package 下的 dist.sha256(下载包)或 source.reference(Git commit)。校验时得一层层查:
- 运行
composer show --installed --no-ansi | grep -E "^(ext-|lib-|[^[:space:]]+\/[^[:space:]]+) "确认当前 vendor 实际装了哪些包 - 在
composer.lock中找到对应 package,提取其dist.sha256 - 用
sha256sum vendor/{vendor}/{package}/composer.json(或 dist 包解压后根目录文件)比对——但注意:Composer 计算哈希的对象是整个 dist zip 解压前原始字节,不是 vendor 目录下任意单个文件 - 所以人工比对不可靠,应优先依赖
--dry-run
真正可靠的校验发生在 composer install 或 update 过程中自动完成,而 --dry-run 是唯一暴露这个过程给你看的开关。别指望靠肉眼核对 lock 文件里的哈希值来确认 vendor 安全——那只是幻觉。











