(PHP 8)
SQLite3::setAuthorizer — 配置一个回调作为授权器,以限制语句可以执行的操作
设置一个回调,SQLite 将在每次执行操作(读取、删除、更新等)时调用它。当从不受信任的来源准备 SQL 语句时,这将用于确保 SQL 语句不会尝试访问它们无权查看的数据,或者尝试执行破坏数据库的恶意语句。例如,应用程序可能允许用户输入任意 SQL 查询以供数据库评估。但应用程序不希望用户能够对数据库进行任意更改。然后,可以在准备用户输入的 SQL 时设置授权器,以禁止除 SELECT 语句以外的所有操作。
授权器回调可能会为 SQLite 准备的每个语句调用多次。一个 SELECT
或 UPDATE
查询将为要读取或更新的每个列调用授权器。
授权器使用最多五个参数调用。第一个参数始终给出,是一个 int(操作代码),与 SQLite3
中的常量匹配。其他参数仅在某些操作中传递。下表根据操作描述了第二个和第三个参数
操作 | 第二个参数 | 第三个参数 |
---|---|---|
SQLite3::CREATE_INDEX | 索引名称 | 表名称 |
SQLite3::CREATE_TABLE | 表名称 | null |
SQLite3::CREATE_TEMP_INDEX | 索引名称 | 表名称 |
SQLite3::CREATE_TEMP_TABLE | 表名称 | null |
SQLite3::CREATE_TEMP_TRIGGER | 触发器名称 | 表名称 |
SQLite3::CREATE_TEMP_VIEW | 视图名称 | null |
SQLite3::CREATE_TRIGGER | 触发器名称 | 表名称 |
SQLite3::CREATE_VIEW | 视图名称 | null |
SQLite3::DELETE | 表名称 | null |
SQLite3::DROP_INDEX | 索引名称 | 表名称 |
SQLite3::DROP_TABLE | 表名称 | null |
SQLite3::DROP_TEMP_INDEX | 索引名称 | 表名称 |
SQLite3::DROP_TEMP_TABLE | 表名称 | null |
SQLite3::DROP_TEMP_TRIGGER | 触发器名称 | 表名称 |
SQLite3::DROP_TEMP_VIEW | 视图名称 | null |
SQLite3::DROP_TRIGGER | 触发器名称 | 表名称 |
SQLite3::DROP_VIEW | 视图名称 | null |
SQLite3::INSERT | 表名称 | null |
SQLite3::PRAGMA | Pragma 名称 | 传递给 pragma 的第一个参数,或 null |
SQLite3::READ | 表名称 | 列名称 |
SQLite3::SELECT | null | null |
SQLite3::TRANSACTION | 操作 | null |
SQLite3::UPDATE | 表名称 | 列名称 |
SQLite3::ATTACH | 文件名 | null |
SQLite3::DETACH | 数据库名称 | null |
SQLite3::ALTER_TABLE | 数据库名称 | 表名称 |
SQLite3::REINDEX | 索引名称 | null |
SQLite3::ANALYZE | 表名称 | null |
SQLite3::CREATE_VTABLE | 表名称 | 模块名称 |
SQLite3::DROP_VTABLE | 表名称 | 模块名称 |
SQLite3::FUNCTION | null | 函数名称 |
SQLite3::SAVEPOINT | 操作 | 保存点名称 |
SQLite3::RECURSIVE | null | null |
如果适用,第 4 个参数将是数据库的名称("main"
、"temp"
等)。
授权器回调的第 5 个参数是负责访问尝试的最内层触发器或视图的名称,或者如果此访问尝试直接来自顶级 SQL 代码,则为 null
。
当回调返回 SQLite3::OK
时,这意味着请求的操作被接受。当回调返回 SQLite3::DENY
时,触发授权器的调用将失败,并显示一条错误消息,解释访问被拒绝的原因。
如果操作代码是 SQLite3::READ
并且回调返回 SQLite3::IGNORE
,则准备好的语句将被构造以在要读取的表列的位置替换为 null
值(如果返回 SQLite3::OK
)。SQLite3::IGNORE
返回值可用于拒绝不受信任的用户访问表的单个列。
当表被 SELECT
引用,但没有从该表中提取任何列值(例如在类似 "SELECT count(*) FROM table"
的查询中)时,SQLite3::READ
授权器回调将为此表调用一次,并使用一个空字符串作为列名称。
如果操作代码是 SQLite3::DELETE
并且回调返回 SQLite3::IGNORE
,则 DELETE 操作将继续进行,但截断优化将被禁用,并且所有行将被单独删除。
一次只能在一个数据库连接上设置单个授权器。对 SQLite3::setAuthorizer() 的每次调用都会覆盖之前的调用。通过安装 null
回调来禁用授权器。默认情况下,授权器处于禁用状态。
授权器回调不得执行任何会修改调用授权器回调的数据库连接的操作。
请注意,授权器仅在准备语句时调用,而不是在执行语句时调用。
有关更多详细信息,请参阅 » SQLite3 文档.
此方法不会抛出任何错误,但如果启用了授权器并返回无效值,则语句准备将抛出错误(或异常,具体取决于使用 SQLite3::enableExceptions() 方法)。
示例 #1 SQLite3::setAuthorizer() 示例
这仅允许访问读取操作,并且仅返回 users
表的某些列。其他列将被替换为 null
。
<?php
$db = new SQLite3('data.sqlite');
$db->exec('CREATE TABLE users (id, name, password);');
$db->exec('INSERT INTO users VALUES (1, \'Pauline\', \'Snails4eva\');');
$allowed_columns = ['id', 'name'];
$db->setAuthorizer(function (int $action, ...$args) use ($allowed_columns) {
if ($action === SQLite3::READ) {
list($table, $column) = $args;
if ($table === 'users' && in_array($column, $allowed_columns) {
return SQLite3::OK;
}
return SQLite3::IGNORE;
}
return SQLite3::DENY;
});
print_r($db->querySingle('SELECT * FROM users WHERE id = 1;'));
以上示例将输出
Array ( [id] => 1 [name] => Pauline [password] => )