addiks / stored-sql
用于在不同环境中处理、建模和执行存储的 SQL(函数、查询、条件等)
Requires
- php: >=8.1
- dasprid/enum: ^1.0
- webmozart/assert: ^1.9
Requires (Dev)
- addiks/more-php-cs-fixers: v0.2.0
- kubawerlos/php-cs-fixer-custom-fixers: ^2.4
- phpstan/phpstan: ^0.12.0
- phpstan/phpstan-webmozart-assert: ^0.12.12
- phpunit/phpunit: ^9.5
- psalm/plugin-phpunit: ^0.15.1
- psr/simple-cache: ^1.0 || ^3.0
- symfony/cache-contracts: *
- symfony/yaml: ^5.2
- vimeo/psalm: ^4.5
Suggests
- psr/simple-cache: For caching without symfony
- symfony/cache-contracts: For caching with symfony
README
警告:未完成,正在开发中!
此库提供了一个非常灵活且动态的工具集,用于分析和操作 SQL 语句和 SQL 段落。与其他 SQL 库相比,它可以处理 SQL 片段。像 WHERE foo.bar = "Lorem"
这样的片段是完美的、有效的 SQL 片段。它可能不能在服务器上直接运行(此库知道这一点),但即使查询的其他部分未知或缺失,也可以对其进行处理。
其主要目的是能够将 SQL 部分存储在数据库中,并用作非常灵活、用户自定义的规则,这些规则可以轻松验证并合并到实际运行的 SQL 查询中。
例如,如果您有一个仓储系统,并希望确定哪个仓库应该完成送货,并且希望这个规则可以在任何时候由用户定义和更改,您可以像这样将规则存储在数据库中
如您所见,我们已经在数据库中存储了非常复杂的规则,而不需要任何额外的表,并且可以充分利用完整的 SQL 功能。
安全问题
因此,为了回答显而易见的问题:这不会是一个巨大的安全风险吗?如果有人输入一个像 DROP TABLE orders
这样的“规则”,它不会删除整个 orders 表吗?
答案是:不会,它只会产生错误。
每个 SQL 片段都会被标记化并解析成 AST 树,您只需查看根节点即可理解查询内容。像 LEFT JOIN foo f ON(f.a=b.id) WHERE f.bar=e.baz
这样的片段只会产生两个根节点:一个 SqlAstJoin
节点和一个 SqlAstWhere
节点,因此您可以非常容易地控制允许哪些类型的 SQL 片段,哪些应该被拒绝。
此外,解析器以模块化方式构建,因此您可以限制它所理解的 SQL。您知道在某个时刻,您只期望有简单的 ORDER BY
片段,这些片段由简单的操作和一些函数(如 COUNT
或 SUM
)组成,那么只需将这些模块包含在解析器中。如果有人试图偷偷摸摸地提交像 ORDER BY EVAL("DROP TABLE orders")
这样的内容,解析器将拒绝对“EVAL”函数的意外调用。
这也自动排除了任何可能成为漏洞的 SQL 特殊性,因为这些特殊性不包括在这个 SQL 库中(除非您自己编写代码)。
简而言之:此库让您控制允许哪些 SQL,哪些不允许。您定义一个白名单,任何不在白名单上的内容都将被拒绝。(类似于论坛中的 HTML 过滤器)
客户端
此库有两个方面:PHP 的服务器端和 TypeScript 编写的客户端。这两个部分都包含相同的动态 SQL 解析器,但客户端还包含一些 UI 代码,以向用户提供一个易于使用的组件来修改 SQL 部分。毕竟,不是每个人都能理解 SQL。
客户端和服务器端都针对相同的测试用例进行了测试,以确保两个解析器兼容。
警告:客户端尚未完成,需要大量工作。