OpenSCA知识小课堂开课了!

今天主要介绍基于composer包管理器的组件成分解析原理。

composer介绍

composer是PHP的依赖管理工具。

开发者受到Node.js的npm及Ruby的bundler启发,composer设计上与两者有诸多相似。

composer的依赖管理文件是composer.json。开发者可以在composer.json中指定每个依赖项的版本范围或使用composer require/update/remove ${name}命令管理依赖项。

如果一个项目中存在composer.json文件,便可以执行composer install命令自动安装当前项目所需的依赖项并生成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为项目声明的许可证,可以是一个字符串或是一个字符串数组。

require-dev为开发环境或测试使用的依赖,require为生产环境使用的依赖,依赖写法为"name":"version",版本可以指定准确版本或一个范围。

解析算法

composer.lock

composer.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.0且<1.2.0

^1.0.2代表版本号需要>=1.0.2且<2.0.0

由此可以构建出当前项目的依赖结构:

实线代表直接依赖,虚线代表间接依赖

图:composer.lock检测结果示例

composer.json

composer.json为开发者管理的依赖管理文件,在未找到composer.lock文件时将解析该文件。

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版本。

因此组件依赖结构就变成了:

按照这种方式层级解析便可获取整个项目的依赖信息。

图:composer.json检测结果示例


感谢每一位开源社区成员对OpenSCA的支持和贡献。

OpenSCA的代码会在GitHub和Gitee持续迭代,欢迎Star和PR,成为我们的开源贡献者,也可提交问题或建议至Issues。我们会参考大家的建议不断完善OpenSCA开源项目,敬请期待更多功能的支持。

OpenSCA官网:

https://opensca.xmirror.cn/

GitHub:

https://github.com/XmirrorSecurity/OpenSCA-cli/releases

Gitee:

https://gitee.com/XmirrorSecurity/OpenSCA-cli/releases

技术文档 | OpenSCA技术原理之composer依赖解析的更多相关文章

  1. 技术文档--studio技术文档

    1.Google推出的毫无疑问,这个是它的最大优势,Android Stuido是Google推出,专门为Android“量身订做”的,是Google大力支持的一款基于IntelliJ IDEA改造的 ...

  2. Atitit usrQBK1600 技术文档的规范标准化解决方案

    Atitit usrQBK1600 技术文档的规范标准化解决方案 1.1. Keyword关键词..展关键词,横向拓展比较,纵向抽象细化拓展知识点1 1.2. 标题必须有高大上词汇,参考文章排行榜,1 ...

  3. Kafka 技术文档

    Kafka 技术文档   目录 1 Kafka创建背景 2 Kafka简介 3 Kafka好处 3.1 解耦 3.2 冗余 3.3 扩展性 3.4 灵活性 & 峰值处理能力 3.5 可恢复性 ...

  4. 使用Jupyter Notebook编写技术文档

    1.jupyter Notebook的组成 这里它的组件及其工程构成,帮助大家更好的用好jupyter Notebook 组件 Jupyter Notebook结合了三个组件: 笔记本Web应用程序: ...

  5. 如何写好技术文档——来自Google十多年的文档经验

    本文大部分内容翻译总结自<Software Engineering at Google> 第10章节 Documentation. 另外,该书电子版近日已经可以免费下载了 https:// ...

  6. RabbitMq 技术文档

    RabbitMq 技术文档 目录 1 AMQP简介 2 AMQP的实现 3 RabbitMQ简介 3.1 概念说明 3.2 消息队列的使用过程 3.3 RabbitMQ的特性 4 RabbitMQ使用 ...

  7. [转]unity3d 脚本参考-技术文档

    unity3d 脚本参考-技术文档 核心提示:一.脚本概览这是一个关于Unity内部脚本如何工作的简单概览.Unity内部的脚本,是通过附加自定义脚本对象到游戏物体组成的.在脚本对象内部不同志的函数被 ...

  8. Umbraco官方技术文档 中文翻译

    Umbraco 官方技术文档中文翻译 http://blog.csdn.net/u014183619/article/details/51919973 http://www.cnblogs.com/m ...

  9. Indri中的动态文档索引技术

    Indri中的动态文档索引技术 戴维 译 摘要: Indri 动态文档索引的实现技术,支持在更新索引的同时处理用户在线查询请求. 文本搜索引擎曾被设计为针对固定的文档集合进行查询,对不少应用来说,这种 ...

  10. [转]chrome技术文档列表

    chrome窗口焦点管理系统 http://www.douban.com/note/32607279/ chrome之TabContents http://www.douban.com/note/32 ...

随机推荐

  1. Go笔记(3)-3种go语言的键盘输入详解

    go语言的键盘输入详解 go语言中有三种输入函数,分别是: fmt.Scanf() 可以按照指定的格式进行输入 fmt.Scanln() 通过指针将值赋值给变量 fmt.Scan() (1)fmt.S ...

  2. 【译】Visual Studio 17.8 中我最喜欢的特性

    对于 Visual Studio 团队来说,这是忙碌的一周,他们准备了 Ignite 和 .NET Conf,并发布了最新版本的 Visual Studio 2022,即17.8版本.有很多很酷的新功 ...

  3. jenkins pipeline语法、自动生成、部署案例

    Jenkins Pipeline是一套插件,支持在Jenkins中实现持续集成和持续交付: pipeline的编写都要写入到一个名为Jenkinsfile的文件中. 流水线脚本管理 Jenkinsfi ...

  4. 信创选国产,Solon v2.6.3 发布

    Solon 是什么框架? Java 新的"生态级"应用开发框架.从零开始构建,有自己的标准规范与开放生态(历时六年,具备全球第二级别的生态规模). 相对于 Spring,有什么特点 ...

  5. 从零玩转系列之微信支付实战PC端支付微信退款接口搭建 | 技术创作特训营第一期

    一.前言 从零玩转系列之微信支付实战PC端支付微信退款接口搭建 | 技术创作特训营第一期 继前文章取消订单接口和查询订单接口此篇为申请退款流程,此篇文章过长我将分几个阶段的文章发布(项目源码都有,小程 ...

  6. MySQL|MySQL事物以及隔离级别

    MySQL 事务主要用于处理操作量大,复杂度高的数据.比如开单,需要添加给订单表增加记录,还需要增加订单的各种相关明细,操作复杂度高,这些操作语句需要构成一个事务.在 MySQL 命令行的默认设置下, ...

  7. IBM DS5020存储更换硬盘操作

    前期准备:笔记本.网线 连接存储控制器操作,在笔记本上安装DS Storage Manager 11 Client,然后在笔记本IP设备为192.168.128.X(A控制器管理口1和2的管理IP地址 ...

  8. 28、Flutter Key详解

    在Flutter中,Key是不能重复使用的,所以Key一般用来做唯一标识.组件在更新的时候,其状态的保 存主要是通过判断组件的类型或者key值是否一致.因此,当各组件的类型不同的时候,类型已经足够 用 ...

  9. IoT与鸿蒙、低代码、生成式AI,引爆技术浪潮——华为云开发者日南京站成功举办

    本文分享自华为云社区<IoT与鸿蒙.低代码.生成式AI,引爆技术浪潮--华为云开发者日南京站成功举办>,作者:华为云社区精选 . 近日,华为云开发者日HDC.Cloud Day南京站成功举 ...

  10. 华为云PB级数据库GaussDB(for Redis)解析第二期:Redis消息队列Stream的应用探讨

    摘要:本文将对Stream的常用命令和应用场景进行介绍,并探讨原生Redis Stream消息队列的缺陷以及GaussDB(for Redis)提供的解决方案,供大家学习和选用. 华为云高斯Redis ...