PHP主|監視文件完整性
關鍵要點
- 監控文件完整性對於網站管理至關重要,它有助於檢測何時意外或惡意添加、修改、刪除或損壞文件。對文件內容進行哈希處理是監控此類更改的可靠方法。
- PHP 的
hash_file()
函數可用於創建用於監控的文件結構配置文件。可以存儲每個文件的哈希值,以便以後進行比較以檢測任何更改。 - 可以設置數據庫表來存儲文件的哈希值,其中
file_path
存儲服務器上文件的路徑,file_hash
存儲文件的哈希值。 - PHP 的
RecursiveDirectoryIterator
類可用於遍歷文件樹並收集用於比較的哈希值。然後可以使用這些哈希值更新integrity_hashes
數據庫。可以使用 PHP 的array_diff_assoc()
函數檢查差異,這有助於識別已添加、刪除或更改的文件。
應對網站管理中的各種情況
考慮一下在管理網站時如何解決以下情況:
- 意外添加、修改或刪除文件
- 惡意添加、修改或刪除文件
- 文件損壞
更重要的是,您是否知道是否發生了這些情況之一?如果您的答案是否定的,請繼續閱讀。在本指南中,我將演示如何創建文件結構配置文件,該配置文件可用於監控文件的完整性。
確定文件是否已被更改的最佳方法是對其內容進行哈希處理。 PHP 提供了多種哈希函數,但對於此項目,我決定使用 hash_file()
函數。它提供了各種不同的哈希算法,如果我決定稍後進行更改,這將使我的代碼易於修改。哈希用於各種應用程序,從密碼保護到 DNA 測序。哈希算法通過將數據轉換為固定大小的可重複加密字符串來工作。它們的設計使得即使對數據進行輕微修改也應該產生非常不同的結果。當兩個或多個不同的數據產生相同的字符串結果時,則稱為“衝突”。每種哈希算法的強度可以通過其速度和衝突概率來衡量。在我的示例中,我將使用 SHA-1 算法,因為它速度快,衝突概率低,並且已被廣泛使用和充分測試。當然,歡迎您研究其他算法並使用任何您喜歡的算法。獲得文件的哈希值後,可以將其存儲起來以便以後進行比較。如果以後對文件進行哈希處理沒有返回與之前相同的哈希字符串,那麼我們就知道該文件已被更改。
數據庫
首先,我們需要佈局一個基本表來存儲文件的哈希值。我將使用以下模式:
CREATE TABLE integrity_hashes ( file_path VARCHAR(200) NOT NULL, file_hash CHAR(40) NOT NULL, PRIMARY KEY (file_path) );
file_path
存儲服務器上文件的路徑,由於該值始終是唯一的(因為兩個文件不能佔用文件系統中的同一位置),因此它是我們的主鍵。我將其最大長度指定為 200 個字符,這應該允許一些較長的文件路徑。 file_hash
存儲文件的哈希值,它將是一個 SHA-1 40 字符的十六進製字符串。
收集文件
下一步是構建文件結構的配置文件。我們定義要開始收集文件的路徑,並遞歸地迭代每個目錄,直到我們覆蓋了文件系統的整個分支,並可以選擇性地排除某些目錄或文件擴展名。我們在遍歷文件樹時收集所需的哈希值,然後將其存儲在數據庫中或用於比較。 PHP 提供了幾種遍歷文件樹的方法;為簡單起見,我將使用 RecursiveDirectoryIterator
類。
<?php define("PATH", "/var/www/"); $files = array(); // 要获取的扩展名,空数组将返回所有扩展名 $ext = array("php"); // 要忽略的目录,空数组将检查所有目录 $skip = array("logs", "logs/traffic"); // 构建配置文件 $dir = new RecursiveDirectoryIterator(PATH); $iter = new RecursiveIteratorIterator($dir); while ($iter->valid()) { // 跳过不需要的目录 if (!$iter->isDot() && !in_array($iter->getSubPath(), $skip)) { // 获取特定文件扩展名 if (!empty($ext)) { // PHP 5.3.4: if (in_array($iter->getExtension(), $ext)) { if (in_array(pathinfo($iter->key(), PATHINFO_EXTENSION), $ext)) { $files[$iter->key()] = hash_file("sha1", $iter->key()); } } else { // 忽略文件扩展名 $files[$iter->key()] = hash_file("sha1", $iter->key()); } } $iter->next(); }
請注意,我在 $skip
數組中兩次引用了相同的文件夾 logs
。僅僅因為我選擇忽略特定目錄並不意味著迭代器也會忽略所有子目錄,這取決於您的需求,這可能很有用或很煩人。 RecursiveDirectoryIterator
類使我們可以訪問多種方法:
-
valid()
檢查我們是否正在使用有效文件 -
isDot()
確定目錄是否為“.”或“..” -
getSubPath()
返回文件指針當前所在的文件夾名稱 -
key()
返回完整路徑和文件名 -
next()
重新啟動循環
還有更多可用的方法,但大多數情況下,上面列出的方法是我們所需的所有方法,儘管在 PHP 5.3.4 中添加了 getExtension()
方法,該方法返回文件擴展名。如果您的 PHP 版本支持它,您可以使用它來過濾不需要的條目,而不是我使用 pathinfo()
所做的操作。執行後,代碼應使用類似於以下內容的結果填充 $files
數組:
<code>Array ( [/var/www/test.php] => b6b7c28e513dac784925665b54088045cf9cbcd3 [/var/www/sub/hello.php] => a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa [/var/www/sub/world.php] => da39a3ee5e6b4b0d3255bfef95601890afd80709 )</code>
構建配置文件後,更新數據庫非常容易。
<?php $db = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASSWORD); // 清除旧记录 $db->query("TRUNCATE integrity_hashes"); // 插入更新的记录 $sql = "INSERT INTO integrity_hashes (file_path, file_hash) VALUES (:path, :hash)"; $sth = $db->prepare($sql); $sth->bindParam(":path", $path); $sth->bindParam(":hash", $hash); foreach ($files as $path => $hash) { $sth->execute(); }
檢查差異
您現在知道如何構建目錄結構的新配置文件以及如何更新數據庫中的記錄。下一步是將其組合到某種實際應用程序中,例如帶有電子郵件通知的 cron 作業、管理界面或任何您喜歡的其他內容。如果您只想收集已更改的文件列表,而不在乎它們如何更改,那麼最簡單的方法是將數據從數據庫提取到類似於 $files
的數組中,然後使用 PHP 的 array_diff_assoc()
函數來去除不需要的內容。
CREATE TABLE integrity_hashes ( file_path VARCHAR(200) NOT NULL, file_hash CHAR(40) NOT NULL, PRIMARY KEY (file_path) );
在此示例中,$diffs
將填充任何發現的差異,或者如果文件結構完整,則它將是一個空數組。與 array_diff()
不同,array_diff_assoc()
將在比較中使用鍵,這在我們發生衝突時很重要,例如兩個空文件具有相同的哈希值。如果您想更進一步,您可以添加一些簡單的邏輯來準確確定文件是如何受到影響的,無論是被刪除、更改還是添加。
<?php define("PATH", "/var/www/"); $files = array(); // 要获取的扩展名,空数组将返回所有扩展名 $ext = array("php"); // 要忽略的目录,空数组将检查所有目录 $skip = array("logs", "logs/traffic"); // 构建配置文件 $dir = new RecursiveDirectoryIterator(PATH); $iter = new RecursiveIteratorIterator($dir); while ($iter->valid()) { // 跳过不需要的目录 if (!$iter->isDot() && !in_array($iter->getSubPath(), $skip)) { // 获取特定文件扩展名 if (!empty($ext)) { // PHP 5.3.4: if (in_array($iter->getExtension(), $ext)) { if (in_array(pathinfo($iter->key(), PATHINFO_EXTENSION), $ext)) { $files[$iter->key()] = hash_file("sha1", $iter->key()); } } else { // 忽略文件扩展名 $files[$iter->key()] = hash_file("sha1", $iter->key()); } } $iter->next(); }
當我們遍歷數據庫中的結果時,我們會進行多次檢查。首先,使用 array_key_exists()
檢查我們的數據庫中的文件路徑是否出現在 $files
中,如果沒有,則該文件必須已被刪除。其次,如果文件存在但哈希值不匹配,則該文件必須已被更改或未更改。我們將每個檢查存儲到名為 $tmp
的臨時數組中,最後,如果 $files
中的數量大於數據庫中的數量,那麼我們就知道那些剩餘的未檢查文件已被添加。完成後,$diffs
要么是一個空數組,要么包含以多維數組形式找到的任何差異,這可能如下所示:
<code>Array ( [/var/www/test.php] => b6b7c28e513dac784925665b54088045cf9cbcd3 [/var/www/sub/hello.php] => a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa [/var/www/sub/world.php] => da39a3ee5e6b4b0d3255bfef95601890afd80709 )</code>
為了以更用戶友好的格式顯示結果(例如管理界面),您可以例如遍歷結果並以項目符號列表的形式輸出它們。
<?php $db = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASSWORD); // 清除旧记录 $db->query("TRUNCATE integrity_hashes"); // 插入更新的记录 $sql = "INSERT INTO integrity_hashes (file_path, file_hash) VALUES (:path, :hash)"; $sth = $db->prepare($sql); $sth->bindParam(":path", $path); $sth->bindParam(":hash", $hash); foreach ($files as $path => $hash) { $sth->execute(); }
此時,您可以提供一個鏈接來觸發使用新的文件結構更新數據庫的操作(在這種情況下,您可能選擇將 $files
存儲在會話變量中),或者如果您不批准差異,您可以根據需要處理它們。
總結
希望本指南能幫助您更好地理解文件完整性監控。在您的網站上安裝此類內容是一種寶貴的安全措施,您可以放心,您的文件將完全按照您的意圖保持不變。當然,不要忘記定期備份。以防萬一。
(此處應保留原文的FAQ部分,因為該部分內容與代碼部分無關,屬於補充說明,不屬於偽原創的範疇)
以上是PHP主|監視文件完整性的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

PHP8.1中的枚舉功能通過定義命名常量增強了代碼的清晰度和類型安全性。 1)枚舉可以是整數、字符串或對象,提高了代碼可讀性和類型安全性。 2)枚舉基於類,支持面向對象特性,如遍歷和反射。 3)枚舉可用於比較和賦值,確保類型安全。 4)枚舉支持添加方法,實現複雜邏輯。 5)嚴格類型檢查和錯誤處理可避免常見錯誤。 6)枚舉減少魔法值,提升可維護性,但需注意性能優化。

會話劫持可以通過以下步驟實現:1.獲取會話ID,2.使用會話ID,3.保持會話活躍。在PHP中防範會話劫持的方法包括:1.使用session_regenerate_id()函數重新生成會話ID,2.通過數據庫存儲會話數據,3.確保所有會話數據通過HTTPS傳輸。

SOLID原則在PHP開發中的應用包括:1.單一職責原則(SRP):每個類只負責一個功能。 2.開閉原則(OCP):通過擴展而非修改實現變化。 3.里氏替換原則(LSP):子類可替換基類而不影響程序正確性。 4.接口隔離原則(ISP):使用細粒度接口避免依賴不使用的方法。 5.依賴倒置原則(DIP):高低層次模塊都依賴於抽象,通過依賴注入實現。

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

RESTAPI設計原則包括資源定義、URI設計、HTTP方法使用、狀態碼使用、版本控制和HATEOAS。 1.資源應使用名詞表示並保持層次結構。 2.HTTP方法應符合其語義,如GET用於獲取資源。 3.狀態碼應正確使用,如404表示資源不存在。 4.版本控制可通過URI或頭部實現。 5.HATEOAS通過響應中的鏈接引導客戶端操作。

在PHP中,異常處理通過try,catch,finally,和throw關鍵字實現。 1)try塊包圍可能拋出異常的代碼;2)catch塊處理異常;3)finally塊確保代碼始終執行;4)throw用於手動拋出異常。這些機制幫助提升代碼的健壯性和可維護性。

匿名類在PHP中的主要作用是創建一次性使用的對象。 1.匿名類允許在代碼中直接定義沒有名字的類,適用於臨時需求。 2.它們可以繼承類或實現接口,增加靈活性。 3.使用時需注意性能和代碼可讀性,避免重複定義相同的匿名類。
