(PHP 8)
SQLite3::setAuthorizer — 設定一個回呼函式作為授權器,以限制敘述句可以執行的操作
設定一個回呼函式,SQLite 每次執行動作(讀取、刪除、更新等)時都會呼叫它。當從不受信任的來源準備 SQL 陳述式時,可以使用此函式來確保 SQL 陳述式不會嘗試存取它們不允許看到的資料,或者不會嘗試執行損壞資料庫的惡意陳述式。例如,應用程式可能允許使用者輸入任意 SQL 查詢以供資料庫評估。但應用程式不希望使用者能夠對資料庫進行任意更改。然後,可以在準備使用者輸入的 SQL 時設置一個授權器,除了 SELECT 陳述式外,其他所有操作都不允許。
對於 SQLite 準備的每個陳述式,授權器回呼函式可能會被呼叫多次。`SELECT` 或 `UPDATE` 查詢會針對每個將被讀取或更新的欄位呼叫授權器。
授權器會以最多五個參數被呼叫。第一個參數始終會提供,是一個 整數(動作代碼),與 `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] => )