mata utama
hash_file()
file_path
menyimpan nilai hash fail. file_hash
RecursiveDirectoryIterator
kemudiannya boleh dikemas kini dengan hash ini. Fungsi integrity_hashes
PHP boleh digunakan untuk memeriksa perbezaan, yang membantu mengenal pasti fail yang telah ditambah, dipadam, atau diubah. array_diff_assoc()
bekerjasama dalam pelbagai situasi dalam pengurusan laman web
Pertimbangkan bagaimana menyelesaikan situasi berikut semasa menguruskan laman web:
Cara terbaik untuk menentukan sama ada fail telah diubah adalah untuk hash kandungannya. PHP menyediakan pelbagai fungsi hash, tetapi untuk projek ini, saya memutuskan untuk menggunakan fungsi
. Ia menyediakan pelbagai algoritma hashing yang berbeza, yang akan menjadikan kod saya mudah diubah suai jika saya memutuskan untuk mengubahnya kemudian. Hash digunakan dalam pelbagai aplikasi, dari perlindungan kata laluan ke penjujukan DNA. Algoritma hashing berfungsi dengan menukar data ke dalam rentetan yang disulitkan berulang saiz tetap. Mereka direka sedemikian rupa sehingga sedikit pengubahsuaian kepada data harus menghasilkan hasil yang sangat berbeza. Apabila dua atau lebih data yang berbeza menghasilkan hasil rentetan yang sama, ia dipanggil "konflik". Kekuatan setiap algoritma hashing dapat diukur dengan kelajuan dan kebarangkalian perlanggaran. Dalam contoh saya, saya akan menggunakan algoritma SHA-1 kerana ia pantas, mempunyai kebarangkalian konflik yang rendah, dan telah digunakan secara meluas dan diuji sepenuhnya. Sudah tentu, anda dialu -alukan untuk menyelidik algoritma lain dan menggunakan sebarang algoritma yang anda suka. Selepas mendapatkan nilai hash fail, ia boleh disimpan untuk perbandingan kemudian. Jika hashing fail kemudian tidak mengembalikan rentetan hash yang sama seperti dahulu, maka kita tahu bahawa fail telah diubah. hash_file()
pangkalan data
Pertama, kita perlu susun atur jadual asas untuk menyimpan nilai hash fail. Saya akan menggunakan corak berikut:CREATE TABLE integrity_hashes ( file_path VARCHAR(200) NOT NULL, file_hash CHAR(40) NOT NULL, PRIMARY KEY (file_path) );
file_path
Laluan ke fail pada pelayan penyimpanan, kerana nilai itu sentiasa unik (kerana dua fail tidak dapat menduduki lokasi yang sama dalam sistem fail), itu adalah kunci utama kami. Saya menetapkan panjang maksimum kepada 200 aksara, yang sepatutnya membolehkan beberapa laluan fail yang lebih lama. file_hash
menyimpan nilai hash fail, yang akan menjadi rentetan heksadesimal SHA-1 40-watak.
Kumpulkan fail
Langkah seterusnya ialah membina fail konfigurasi untuk struktur fail. Kami mentakrifkan jalan untuk mula mengumpul fail dan melepasi setiap direktori secara rekursif sehingga kami menulis ganti seluruh cawangan sistem fail dan secara pilihan boleh mengecualikan direktori atau sambungan fail tertentu. Kami mengumpul nilai hash yang diperlukan apabila melintasi pokok fail dan kemudian simpan dalam pangkalan data atau untuk perbandingan. PHP menyediakan beberapa cara untuk melintasi pokok fail; 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(); }
. Hanya kerana saya memilih untuk mengabaikan direktori tertentu tidak bermakna bahawa pemalar juga mengabaikan semua subdirektor, bergantung kepada keperluan anda, yang boleh berguna atau menjengkelkan. Kelas $skip
memberi kita akses kepada pelbagai kaedah: logs
RecursiveDirectoryIterator
valid()
isDot()
kembali ke nama folder di mana penunjuk fail kini terletak getSubPath()
Kembalikan laluan penuh dan nama fail key()
mulakan semula gelung next()
Terdapat banyak lagi kaedah yang tersedia, tetapi kebanyakan masa yang disenaraikan di atas adalah semua kaedah yang kita perlukan, walaupun kaedah dengan hasil yang serupa dengan: getExtension()
pathinfo()
$files
Selepas membina fail konfigurasi, sangat mudah untuk mengemas kini pangkalan data.
<code>Array ( [/var/www/test.php] => b6b7c28e513dac784925665b54088045cf9cbcd3 [/var/www/sub/hello.php] => a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa [/var/www/sub/world.php] => da39a3ee5e6b4b0d3255bfef95601890afd80709 )</code>
Periksa perbezaan
<?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(); }
anda sekarang tahu bagaimana untuk membina fail konfigurasi baru untuk struktur direktori dan bagaimana untuk mengemas kini rekod dalam pangkalan data. Langkah seterusnya adalah untuk menggabungkannya ke dalam beberapa jenis aplikasi sebenar, seperti pekerjaan cron dengan pemberitahuan e -mel, antara muka admin, atau apa sahaja yang anda suka. Jika anda hanya ingin mengumpul senarai fail yang diubah tanpa peduli bagaimana mereka berubah, cara yang paling mudah adalah untuk mengekstrak data dari pangkalan data ke dalam array yang serupa dengan dan menggunakan fungsi PHP
untuk menghapuskan kandungan yang tidak diingini.CREATE TABLE integrity_hashes ( file_path VARCHAR(200) NOT NULL, file_hash CHAR(40) NOT NULL, PRIMARY KEY (file_path) );
Dalam contoh ini, $diffs
akan dihuni dengan sebarang perbezaan yang dijumpai, atau jika struktur fail selesai, ia akan menjadi array kosong. Tidak seperti array_diff()
, array_diff_assoc()
akan menggunakan kunci berbanding, yang penting apabila kita bertentangan, seperti dua fail kosong mempunyai nilai hash yang sama. Jika anda ingin melangkah lebih jauh, anda boleh menambah beberapa logik mudah untuk menentukan secara tepat bagaimana fail itu terjejas, sama ada ia dipadam, diubah, atau ditambah.
<?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(); }
Apabila kita melintasi hasil dalam pangkalan data, kita melakukan beberapa cek. Pertama, gunakan array_key_exists()
untuk memeriksa sama ada laluan fail dalam pangkalan data kami muncul dalam $files
, dan jika tidak, fail mesti dipadamkan. Kedua, jika fail itu wujud tetapi hash tidak sepadan, fail mesti diubah atau tidak diubah. Kami menyimpan setiap cek ke dalam array sementara yang dipanggil $tmp
dan akhirnya, jika nombor dalam $files
lebih besar daripada nombor dalam pangkalan data, maka kami tahu bahawa fail yang tidak terkawal telah ditambah. Setelah selesai, $diffs
sama ada array kosong atau mengandungi sebarang perbezaan yang terdapat dalam bentuk array multidimensi, yang mungkin kelihatan seperti ini:
<code>Array ( [/var/www/test.php] => b6b7c28e513dac784925665b54088045cf9cbcd3 [/var/www/sub/hello.php] => a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa [/var/www/sub/world.php] => da39a3ee5e6b4b0d3255bfef95601890afd80709 )</code>
Untuk memaparkan hasil dalam format yang lebih mesra pengguna (seperti antara muka pengurusan), anda boleh misalnya melelehkan hasil dan mengeluarkannya sebagai senarai bulleted.
<?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(); }
Pada ketika ini, anda boleh memberikan pautan untuk mencetuskan operasi mengemas kini pangkalan data dengan struktur fail baru (dalam hal ini anda mungkin memilih untuk menyimpan $files
dalam pemboleh ubah sesi), atau jika anda tidak meluluskan perbezaan, anda boleh mengendalikannya seperti yang diperlukan.
Ringkasan
Saya harap panduan ini dapat membantu anda memahami pemantauan integriti fail. Memasang kandungan sedemikian di laman web anda adalah langkah keselamatan yang berharga dan anda boleh yakin bahawa fail anda akan tetap sama seperti yang anda inginkan. Sudah tentu, jangan lupa untuk menyokong secara teratur. Dalam kes.
(bahagian FAQ dari teks asal harus dikekalkan di sini, kerana kandungan bahagian ini tidak ada kaitan dengan bahagian kod, milik penerangan tambahan, dan tidak jatuh ke dalam kategori pseudo-asal)
Atas ialah kandungan terperinci PHP Master | Memantau integriti fail. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!