Maison >développement back-end >tutoriel php >PHP Master | Surveillance de l'intégrité du fichier
Points clés
hash_file()
peut être utilisée pour créer un fichier de configuration de structure de fichiers pour la surveillance. La valeur de hachage de chaque fichier peut être stockée pour des comparaisons ultérieures pour détecter toute modification. file_path
stocke le chemin d'accès du fichier sur le serveur, et file_hash
stocke la valeur de hachage d'un fichier. RecursiveDirectoryIterator
peut être utilisée pour traverser l'arborescence de fichiers et collecter des hachages pour comparaison. La base de données integrity_hashes
peut ensuite être mise à jour avec ces hachages. La fonction array_diff_assoc()
de PHP peut être utilisée pour vérifier les différences, ce qui aide à identifier les fichiers qui ont été ajoutés, supprimés ou modifiés. Collaborer sur diverses situations dans la gestion des sites Web
Considérez comment résoudre les situations suivantes lors de la gestion d'un site Web:
Plus important encore, savez-vous si l'un d'eux se produit? Si votre réponse est non, veuillez continuer à lire. Dans ce guide, je vais montrer comment créer un fichier de configuration de structure de fichiers qui peut être utilisé pour surveiller l'intégrité des fichiers.
La meilleure façon de déterminer si un fichier a été modifié est de hacher son contenu. PHP fournit plusieurs fonctions de hachage, mais pour ce projet, j'ai décidé d'utiliser la fonction hash_file()
. Il fournit une variété d'algorithmes de hachage différents, ce qui rendra mon code facile à modifier si je décide de le modifier plus tard. Le hachage est utilisé dans une variété d'applications, de la protection des mots de passe au séquençage de l'ADN. L'algorithme de hachage fonctionne en convertissant les données en une chaîne cryptée répétable de taille fixe. Ils sont conçus de telle sorte que même de légères modifications des données devraient produire des résultats très différents. Lorsque deux données différentes ou plus produisent le même résultat de chaîne, elle est appelée "conflit". La force de chaque algorithme de hachage peut être mesurée par sa vitesse et sa probabilité de collision. Dans mon exemple, j'utiliserai l'algorithme SHA-1 car il est rapide, a une faible probabilité de conflit et a été largement utilisé et entièrement testé. Bien sûr, vous êtes invités à rechercher d'autres algorithmes et à utiliser tout algorithme que vous aimez. Après avoir obtenu la valeur de hachage du fichier, il peut être stocké pour une comparaison ultérieure. Si le hachage du fichier ne renvoie pas plus tard la même chaîne de hachage qu'auparavant, nous savons que le fichier a été modifié.
Base de données
Tout d'abord, nous devons disposer une table de base pour stocker la valeur de hachage du fichier. J'utiliserai le modèle suivant:
CREATE TABLE integrity_hashes ( file_path VARCHAR(200) NOT NULL, file_hash CHAR(40) NOT NULL, PRIMARY KEY (file_path) );
file_path
Le chemin d'accès au fichier sur le serveur de stockage, car la valeur est toujours unique (car deux fichiers ne peuvent pas occuper le même emplacement dans le système de fichiers), c'est notre clé principale. J'ai spécifié sa longueur maximale à 200 caractères, ce qui devrait permettre des chemins de fichier plus longs. file_hash
stocke la valeur de hachage du fichier, qui sera une chaîne hexadécimale SHA-1 à 40 caractères.
Collectez des fichiers
L'étape suivante consiste à créer le fichier de configuration de la structure du fichier. Nous définissons le chemin d'accès pour commencer à collectionner des fichiers et itérer sur chaque répertoire récursivement jusqu'à ce que nous écrasons toute la branche du système de fichiers et pouvons éventuellement exclure certains répertoires ou extensions de fichiers. Nous collectons les valeurs de hachage requises lors de la traversée de l'arborescence de fichiers, puis la stockons dans la base de données ou à titre de comparaison. PHP fournit plusieurs façons de traverser l'arborescence de fichiers; 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(); }Notez que j'ai référencé le même dossier deux fois dans le tableau
. Ce n'est pas parce que j'ai choisi d'ignorer un répertoire spécifique que l'itérateur ignore également tous les sous-directeurs, selon vos besoins, qui peuvent être utiles ou ennuyeux. La classe $skip
nous donne accès à plusieurs méthodes: logs
RecursiveDirectoryIterator
valid()
isDot()
Retournez au nom du dossier où le pointeur de fichier est actuellement situé getSubPath()
Renvoie le chemin complet et le nom du fichier key()
redémarrer la boucle next()
Il existe de nombreuses autres méthodes disponibles, mais la plupart du temps, les éléments ci-dessus sont toutes les méthodes dont nous avons besoin, bien que la méthode avec des résultats similaires à: getExtension()
pathinfo()
$files
Après la création du fichier de configuration, il est très facile de mettre à jour la base de données.
<code>Array ( [/var/www/test.php] => b6b7c28e513dac784925665b54088045cf9cbcd3 [/var/www/sub/hello.php] => a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa [/var/www/sub/world.php] => da39a3ee5e6b4b0d3255bfef95601890afd80709 )</code>
Vérifiez la différence
<?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(); }
Vous savez maintenant comment créer un nouveau fichier de configuration pour la structure du répertoire et comment mettre à jour les enregistrements dans la base de données. L'étape suivante consiste à le combiner dans une sorte d'application réelle, comme un travail cron avec des notifications par e-mail, une interface d'administration ou tout ce que vous aimez. Si vous souhaitez simplement collecter une liste de fichiers modifiés sans se soucier de leur changement, le moyen le plus simple consiste à extraire les données de la base de données dans un tableau similaire à et à utiliser la fonction PHP
pour supprimer le contenu indésirable.CREATE TABLE integrity_hashes ( file_path VARCHAR(200) NOT NULL, file_hash CHAR(40) NOT NULL, PRIMARY KEY (file_path) );
Dans cet exemple, $diffs
sera rempli avec toutes les différences trouvées, ou si la structure de fichier est terminée, ce sera un tableau vide. Contrairement à array_diff()
, array_diff_assoc()
utilisera la clé en comparaison, ce qui est important lorsque nous confrontésons, comme deux fichiers vides, la même valeur de hachage. Si vous souhaitez aller plus loin, vous pouvez ajouter une logique simple pour déterminer avec précision comment le fichier est affecté, qu'il soit supprimé, modifié ou ajouté.
<?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(); }
Lorsque nous traversons les résultats dans la base de données, nous effectuons plusieurs vérifications. Tout d'abord, utilisez array_key_exists()
pour vérifier si le chemin du fichier dans notre base de données apparaît dans $files
, et sinon, le fichier doit avoir été supprimé. Deuxièmement, si le fichier existe mais que le hachage ne correspond pas, le fichier doit avoir été modifié ou non modifié. Nous stockons chaque vérification dans un tableau temporaire appelé $tmp
et enfin, si le nombre dans $files
est supérieur au nombre de la base de données, nous savons que les fichiers non contrôlés restants ont été ajoutés. Une fois terminé, $diffs
est soit un tableau vide, soit contient des différences trouvées sous la forme d'un tableau multidimensionnel, qui pourrait ressembler à ceci:
<code>Array ( [/var/www/test.php] => b6b7c28e513dac784925665b54088045cf9cbcd3 [/var/www/sub/hello.php] => a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa [/var/www/sub/world.php] => da39a3ee5e6b4b0d3255bfef95601890afd80709 )</code>
Pour afficher les résultats dans un format plus convivial (tel que l'interface de gestion), vous pouvez par exemple itérer sur les résultats et les publier sous forme de listes à puces.
<?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(); }
À ce stade, vous pouvez fournir un lien pour déclencher le fonctionnement de la mise à jour de la base de données avec la nouvelle structure de fichiers (auquel cas vous pouvez choisir de stocker $files
dans une variable de session), ou si vous n'approuvez pas les différences, vous pouvez les gérer selon les besoins.
Résumé
J'espère que ce guide vous aidera à mieux comprendre la surveillance de l'intégrité des fichiers. L'installation d'un tel contenu sur votre site Web est une mesure de sécurité précieuse et vous pouvez être assuré que vos fichiers resteront les mêmes que vous l'intention. Bien sûr, n'oubliez pas de sauvegarder régulièrement. au cas où.
(La partie FAQ du texte d'origine doit être conservée ici, car le contenu de cette partie n'a rien à voir avec la partie du code, appartient à la description supplémentaire et ne tombe pas dans la catégorie de la pseudo-originalité)
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!