2. 许可证识别基础
在开源合规工作中,许可证识别不是“看一眼 LICENSE 文件”这么简单。一个真实项目里,许可证信息可能分散在仓库根目录、子模块、包管理器元数据、源文件头注释、构建脚本甚至文档中,而且不同位置的信息可能互相矛盾。本节的目标是建立一套可复用的定位与验证方法:先知道去哪里找,再知道怎么读,最后知道如何判断“这个标识符是否可信”。
一、许可证信息的四个主要来源
从工程实践看,许可证信息通常出现在以下四类位置,它们的权威性和用途各不相同。
- 仓库根目录的许可证文件:最常见的是
LICENSE、LICENSE.txt、LICENSE.md、COPYING、COPYING.LESSER。这是项目整体授权声明的主要载体,通常包含完整许可证正文。 - 包管理器元数据:如 npm 的
package.json中的license字段、Python 的pyproject.toml或setup.py中的license、Maven 的pom.xml中的<licenses>、Rust 的Cargo.toml中的license字段。这些字段通常使用 SPDX 标识符,便于机器读取。 - 源文件头部的版权与许可声明:例如
/* SPDX-License-Identifier: MIT */或// Copyright 2023 Example Corp. Licensed under Apache-2.0.。这类声明粒度最细,能反映单个文件的授权情况。 - 项目文档与 README:README 中常出现“本项目采用 MIT 许可证”等描述,但它是叙述性文字,权威性低于 LICENSE 文件和 SPDX 标识符,只能作为线索。
二、SPDX 标识符的读取与验证
SPDX(Software Package Data Exchange)标识符是许可证的“标准缩写”,例如 MIT、Apache-2.0、GPL-3.0-only、BSD-3-Clause、MPL-2.0。它的价值在于消除歧义:同样是“GPL”,GPL-2.0-only、GPL-2.0-or-later、GPL-3.0-only 的法律含义完全不同。
读取 SPDX 标识符时,要特别注意以下几种写法:
- 带
-only与-or-later:GPL-2.0-only表示仅限该版本;GPL-2.0-or-later表示可使用该版本或任何后续版本。后者对使用者更宽松,但合规义务的版本选择需要明确。 - 带
+的旧式写法:如GPL-2.0+,在 SPDX 中应规范化为GPL-2.0-or-later。 - 复合表达式:如
MIT OR Apache-2.0、Apache-2.0 AND MIT、GPL-2.0-only WITH Classpath-exception-2.0。这里的OR、AND、WITH是逻辑运算符,含义不同:OR表示可任选其一,AND表示需同时满足,WITH表示附加例外条款。 - 非标准写法:如
MIT License、Apache 2、GPLv3。这些不是合法 SPDX 标识符,需要人工映射到标准标识符后再判断。
验证 SPDX 标识符是否有效,可以对照 SPDX 官方许可证列表。一个实用的检查流程是:先确认标识符是否在官方列表中;再确认表达式语法是否正确;最后确认该标识符与 LICENSE 正文是否匹配。例如,元数据写 MIT,但 LICENSE 文件正文是 Apache-2.0 的完整条款,这就属于典型的不一致,需要以 LICENSE 正文为准并进一步排查。
三、OSI 认证与“开源”判断
OSI(Open Source Initiative)维护着开源定义(OSD)并认证许可证。看到某个许可证名称时,不要默认它就是 OSI 认证的开源许可证。例如,SSPL、BSL 等常被误认为开源,但它们并未通过 OSI 认证,商业使用限制明显。判断一个许可证是否属于 OSI 认证,应查询 OSI 官方许可证列表,而不是依赖项目自我描述。
需要区分三个层次:OSI 认证说明该许可证符合开源定义;SPDX 收录说明该许可证有标准标识符,便于机器处理;FSF 自由许可证则从自由软件角度评估。三者有交集但不完全等同。合规判断中,通常以 SPDX 标识符作为机器可读入口,以 OSI 认证状态作为“是否开源”的初步依据,再结合具体条款评估商业使用风险。
四、定位与验证的实操路径
下面给出一条可直接执行的检查路径,适用于对一个新引入的依赖或代码仓库做许可证识别。
- 在仓库根目录查找
LICENSE*、COPYING*文件,记录文件名与正文首行。 - 打开包管理器元数据,提取
license或licenses字段,记录原始字符串。 - 随机抽取 3~5 个源文件,查看头部是否有
SPDX-License-Identifier或版权声明。 - 将元数据中的标识符与 LICENSE 正文比对,确认是否一致。
- 若标识符为复合表达式,拆解
OR/AND/WITH结构,明确可选路径与附加义务。 - 查询 SPDX 与 OSI 官方列表,确认标识符合法性与开源认证状态。
- 记录不一致项、缺失项和待确认项,形成初步识别结论。
例如,某 npm 包的 package.json 中写 "license": "MIT",仓库根目录存在 LICENSE 文件,正文为 MIT 标准条款,源文件头部有 SPDX-License-Identifier: MIT。三者一致,可初步判定为 MIT。若元数据写 "license": "GPL-3.0",而 LICENSE 正文是 GPL-3.0 完整文本,但源文件头写 SPDX-License-Identifier: GPL-2.0-only,则存在版本冲突,需要进一步确认项目实际授权意图,不能直接按元数据下结论。
五、常见不一致与处理原则
实际项目中最容易出问题的是“元数据与正文不一致”。常见情形包括:元数据写 MIT,LICENSE 正文却是 BSD-3-Clause;元数据写 Apache-2.0,但源文件头写 GPL-2.0-only;元数据写 ISC,仓库中根本没有 LICENSE 文件。处理原则是:以更具体、更正式的授权文本为准,同时记录冲突。LICENSE 正文通常比元数据字段更正式;源文件头声明在涉及单文件授权时具有独立意义。若冲突无法通过项目文档解释,应视为高风险项,进入人工复核。
六、识别记录表示例
为了让识别结果可追溯,建议对每个依赖或仓库维护一份简表。以下为示例结构,字段可根据团队需要增减。
| 检查项 | 示例值 | 判断要点 |
|---|---|---|
| 仓库 LICENSE 文件 | LICENSE(MIT 正文) | 是否存在、正文首行是否可识别 |
| 包管理器 license 字段 | "license": "MIT" |
是否为合法 SPDX 标识符 |
| 源文件头 SPDX | SPDX-License-Identifier: MIT |
抽查文件是否一致 |
| SPDX 表达式 | MIT OR Apache-2.0 |
拆解 OR/AND/WITH 结构 |
| OSI 认证 | 是 | 查询 OSI 官方列表确认 |
| 一致性结论 | 一致 | 一致 / 冲突 / 缺失 / 待复核 |
完成上述定位与验证后,你得到的不只是一个许可证名称,而是一条可追溯的证据链:信息来自哪里、原始字符串是什么、是否经过 SPDX 规范化、是否通过 OSI 认证、是否存在冲突。这条证据链是后续商业使用风险判断的基础。下一阶段的工作,才是基于这些识别结果去分析具体义务与风险。