(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 |
如果适用,第四个参数将是数据库的名称("main"
,"temp"
等)。
授权器回调函数的第五个参数是负责访问尝试的最内层触发器或视图的名称,如果此访问尝试直接来自顶级 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] => )