当前位置: 首页 > 后端技术 > PHP

技术文件-OpenSCA技术原理之Composer依赖分析

时间:2023-03-29 23:15:10 PHP

OpenSCA知识课开课啦!今天主要介绍基于composer包管理器的组件组成分析原理。Composer简介Composer是PHP的依赖管理工具。开发者受到Node.js的npm和Ruby的bundler的启发,而composer在设计上与两者有很多相似之处。Composer的依赖管理文件是composer.json。开发者可以在composer.json中为每个依赖指定版本范围,或者使用composerrequire/update/remove${name}命令来管理依赖。如果项目中存在composer.json文件,可以执行composerinstall命令自动安装当前项目所需的依赖,并生成composer.lock文件。composer.json完整的文件结构如下:{"name":"cakephp/app","type":"project","license":"MIT","require":{"php":">=7.2","cakephp/cakephp":"^4.3","cakephp/migrations":"^3.2","cakephp/plugin-installer":"^1.3","mobiledetect/mobiledetectlib":"^2.8"},"require-dev":{"cakephp/bake":"^2.6","cakephp/cakephp-codesniffer":"^4.5","cakephp/debug_kit":"^4.5","josegonzalez/dotenv":"^3.2","phpunit/phpunit":"~8.5.0||^9.3"},}其中name为项目名;type是包的类型,有四种类型:library、project、metapackage和composer-plugin,默认是library;license是项目声明的license,可以是字符串或者a一个字符串数组require-dev是开发环境或测试使用的依赖,require是生产环境使用的依赖。依赖写成“名称”:“版本”,版本可以指定一个确切的版本或范围。解析算法composer.lockcomposer.lock文件是一个自动生成的文件,可以准确定位PHP项目使用的依赖和版本,所以优先解析composer.lock文件。composer.lock文件结构如下:{"packages":[{"name":"a","version":"1.1.0","require":{"c":"1.1.*"}},{"name":"b","version":"1.2.2","require":{"c":"^1.0.2"}},{"name":"c","version":"1.1.2"}],"packages-dev":[]}其中packages和packages-dev字段包含了项目使用的所有直接和间接依赖关系,记录了组件之间的依赖关系,packages是生产环境的依赖,packages-dev是开发环境的依赖。例子:{"name":"a","version":"1.1.0","require":{"c":"1.1.*"}}表示项目依赖1.1.0版本的组件a,并且组件依赖于版本被限制为1.1.*的组件c。同样可以看出,项目依赖1.2.2版本的组件b,而这个组件又依赖版本被约束为^1.0.2的组件c。并且组件a和组件b都不依赖其他依赖,可见这两个组件是项目的直接依赖。注:1.1.*表示版本号需要>=1.1.0and<1.2.0^1.0.2表示版本号需要>=1.0.2and<2.0.0,所以依赖结构当前项目可构建的:实线表示直接依赖,虚线表示间接依赖composer.json只包含直接依赖。当项目构建时,所需的间接依赖将从composer仓库下载并构建到一个composer.lock文件中。因此,可以模拟composer构建过程,获取项目引用的组件依赖。composer.json文件结构如下:{"name":"foo","type":"project","license":"MIT","require":{"a":"^1.1.0","b":"^1.2.0",},"require-dev":{},}require是项目实际使用的直接依赖,require-dev是项目开发时使用的直接依赖。例如:"a":"^1.1.0"表示项目依赖版本约束为^1.1.0的组件a。"b":"^1.2.0"表示项目依赖版本约束为^1.2.0的组件b。从这里的分析,我们可以总结出下图中的依赖关系:实线表示直接依赖关系。通过这个依赖关系,我们可以看到项目组件的直接依赖关系和组件的版本范围,但是无法得知组件依赖的具体版本。在没有composer.lock文件的情况下,为了进一步获取依赖和间接依赖的确切版本,需要从composer仓库下载相应组件的详细信息。例如组件a的详细信息结构为:{"packages":{"a":[{"version":"1.0.1","require":{"c":"^1.0.0"}},{"version":"1.1.0","require":{"c":"^1.1.0"}}]}}其中packages字段是组件和各个版本信息的映射,以及require字段是组件的依赖信息。本例中组件a的约束为^1.1.0,要求版本号>=1.1.0且<2.0.0,所以选择1.1.0版本。于是,组件依赖结构就变成了:这样,通过层次分析就可以得到整个项目的依赖信息。感谢开源社区的每一位成员对OpenSCA的支持和贡献。OpenSCA的代码会在GitHub和Gitee上不断迭代。欢迎Star和PR成为我们的开源贡献者,也可以向Issues提交问题或建议。我们将参考您的建议不断完善OpenSCA开源项目,更多功能支持敬请期待。OpenSCA官网:https://opensca.xmirror.cn/GitHub:https://github.com/XmirrorSecurity/OpenSCA-cli/releasesGitee:https://gitee.com/XmirrorSecurity/OpenSCA-cli/releases