PHP Conference Japan 2024

SQLite3::setAuthorizer

(PHP 8)

SQLite3::setAuthorizer配置回调函数作为授权器,以限制语句可以执行的操作

描述

public SQLite3::setAuthorizer(?callable $callback): bool

设置一个回调函数,SQLite 每次执行操作(读取、删除、更新等)时都会调用该函数。当从不受信任的来源准备 SQL 语句时,这用于确保 SQL 语句不会尝试访问它们无权查看的数据,或者不会尝试执行破坏数据库的恶意语句。例如,应用程序可以允许用户输入任意 SQL 查询以供数据库评估。但应用程序不希望用户能够对数据库进行任意更改。然后,在准备用户输入的 SQL 时,可以设置一个授权器,该授权器只允许 SELECT 语句,而不允许其他任何操作。

对于 SQLite 准备的每个语句,授权器回调函数都可能被调用多次。一个 SELECTUPDATE 查询将为每个要读取或更新的列调用授权器。

授权器使用多达五个参数调用。第一个参数始终给出,是一个 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::PRAGMAPragma 名称传递给 pragma 的第一个参数,或 null
SQLite3::READ表名列名
SQLite3::SELECTnullnull
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::FUNCTIONnull函数名称
SQLite3::SAVEPOINT操作保存点名称
SQLite3::RECURSIVEnullnull

如果适用,第四个参数将是数据库的名称("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 文档

参数

callback

要调用的 callable

如果传递 null,这将禁用当前的授权器回调函数。

返回值

成功时返回 true,失败时返回 false

错误/异常

此方法不会引发任何错误,但是如果启用了授权器并返回无效值,则语句准备将引发错误(或异常,具体取决于 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] =>
)
添加备注

用户贡献的备注

此页面没有用户贡献的备注。
To Top