Java -Détecter le branchement d’une clé USB
Pour mon projet de BTS, j’ai eu besoin de détecter l’insertion d’une clé USB spécifique.
Java ne propose pas de méthode, technologie pour faire cela. L’idée est de créer un fichier d’identification sur la clé USB et sur le pc, sur lesquels vous générez un identifiant identique pour les deux fichiers. C’est grâce à ce fichier et cet identifiant que nous pourrons détecter si la clé branché est bien celle que nous voulons surveiller.
Vous avez donc deux étapes, l’une pour la création de la clé avec la génération des idéntifiants et la détection de la clé. La création de la clé se fait à l’aide d’une commande dos.
Vous avez besoin d’un dossier SHZ placé à la racine du disque C (C:\SHZ), d’un fichier id_key (C:\SHZ\ id_key), d’un sous dossier tmp (C:\SHZ\tmp) et d’un fichier clean_usb.bat (C:\SHZ\tmp\clean_usb.bat).
Voici l’algorithme pour la création d’une clé USB :
L’algorithme pour la détection de la clé :
Notez que lors du formatage de la clé, je lui donne un nom (KEY) et il est ensuite utilisé pour la détection.
Je n’explique le code, les algorithmes sont assez explicites. Je vous mets un projet d’exemple, attention à la clé que vous sélectionner, elle est formatée directement.
La classe gestion_Usb y a été modifié pour pouvoir être gérer par un timer.
Pour l’utilisation de la classe pour la création d’une clé, vous devez dans un premier définir sur quel port vous voulez travailler avec setPort, ensuite vous devez créer le fichier batch avec create_batch_file, puis demander le formatage de clé avec prepare_usb et enfin synchroniser l’id pc et clé avec Create_AND_SynchID.
Pour la détection, vous avez juste besoin d’appeler la méthode detect_key de façon périodique (avec un timer comme plus haut) ou événementiel (clique bouton).
Notez que ce système pourrait être amélioré en récupérant le SERIAL NUMBER directement du lecteur. Vous pouvez faire cela à l’aide de cette commande :
wmic diskdrive get serialnumber.
Vous obtiendrez les SerialNumber des lecteurs présents.
Projet d’exemple : USB_Detection
Classe Gestion_USB :
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileSystemView;
/**
*
* @author Luyer Romain
* Préparation et Détection de la Clé USB - Listing des ports -
*/
public class Gestion_Usb {
private IHM ihm;
// Attribut static car on doit savoir à niomporte quel moment sur quel port communiquer
public static String Port;
//Instanciation d'un objet pour pour obtenir une vue sur des fichiers
FileSystemView fsv = new javax.swing.JFileChooser().getFileSystemView();
public Gestion_Usb() {
}
public void setPort(String Port) {
this.Port = Port.substring(0, Port.length() - 1);
}
public void SetLienIhm(IHM ihm) {
this.ihm = ihm;
}
/**
* Génère un Id unique aléatoire (identifiant de lecteur)
* Création d'un fichier pc et usb contenant cet id
*/
public void Create_AND_SynchID() {
PrintWriter writer_key = null;
PrintWriter writer_PC = null;
try {
//Génération de l'id
String uniqueID = UUID.randomUUID().toString();
//création du fichier clé usb
writer_key = new PrintWriter(this.Port + "\\" + "SHZ" + "\\id_key", "UTF-8");
//création du fichier pc
writer_PC = new PrintWriter("C:\\" + "SHZ" + "\\id_key", "UTF-8");
//on enregistre l'identifiant
writer_key.println(uniqueID);
writer_PC.println(uniqueID);
//on ferme les fichiers
writer_key.close();
writer_PC.close();
} catch (FileNotFoundException | UnsupportedEncodingException ex) {
JOptionPane.showMessageDialog(null, ex.getMessage() + " !", "Erreur : Create_AND_SynchID", JOptionPane.ERROR_MESSAGE);
Logger.getLogger(Gestion_Usb.class.getName()).log(Level.SEVERE, null, ex);
} finally {
writer_key.close();
writer_PC.close();
}
}
/**
* Permet d'obtenir la liste des ports/lecteurs présents
*/
public void ListPortUSB() {
File[] drive = File.listRoots();
ihm.add_combobox(drive);
}
/**
* Créer un fichier batch qui formate la clé sélectionnée en FAT32 avec nom
* Key
*/
public void create_batch_file() {
PrintWriter writer = null;
try {
//Création du fichier
writer = new PrintWriter("C:\\SHZ\\tmp\\clean_usb.bat", "UTF-8");
//on erit nos données
writer.println("@ echo off");
writer.println("echo | format " + this.Port + " /FS:FAT32 /Q /V:Key");
writer.println("exit");
//on ferme
writer.close();
} catch (FileNotFoundException | UnsupportedEncodingException ex) {
JOptionPane.showMessageDialog(null, ex.getMessage() + " !", "Erreur : create_batch_file", JOptionPane.ERROR_MESSAGE);
Logger.getLogger(Gestion_Usb.class.getName()).log(Level.SEVERE, null, ex);
} finally {
writer.close();
}
}
/**
* Prépare la clé usb en éxécutant le fichier batch et créer des répertoires
* pour de futures utilisations
*
* @throws IOException
* @throws InterruptedException
*/
public void prepare_usb() throws IOException, InterruptedException {
//On créer un processus qui lance notre fichier batch sans confirmation
ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/C", "C:\\SHZ\\tmp\\clean_usb.bat");
Process p = pb.start(); // on lance notre processus
p.waitFor(); // tant que le formattage de clé n'est pas finnis
// On créer notre dossier
new File(Gestion_Usb.Port + "\\" + "SHZ").mkdir();
}
/**
*Regarde si l'id pc correspond à celui de clé
* @param letter lettre du lecteur sur lequel on veut travailler
* @return identifiant de lecteur
*/
private String GetIdKey(String letter) {
String ID_key = null;
FileReader fr_fichier_key = null;
try {
//lecteur du fichier
fr_fichier_key = new FileReader(letter + "\\SHZ" + "\\id_key");
BufferedReader Br_fichier_key = new BufferedReader(fr_fichier_key);
ID_key = Br_fichier_key.readLine();
} catch (FileNotFoundException ex) {
JOptionPane.showMessageDialog(null, ex.getMessage() + " !", "Erreur : GetIdKey | FileNotFoundException", JOptionPane.ERROR_MESSAGE);
Logger.getLogger(Gestion_Usb.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, ex.getMessage() + " !", "Erreur : GetIdKey | IOException", JOptionPane.ERROR_MESSAGE);
Logger.getLogger(Gestion_Usb.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
//on ferme le fichier
fr_fichier_key.close();
} catch (IOException ex) {
Logger.getLogger(Gestion_Usb.class.getName()).log(Level.SEVERE, null, ex);
}
}
return ID_key;
}
/**
* @return 1 si la clé est bien detectée
* @return -1 si aucune cle comptabile n'est détecté
* @return 0 si une clé est détecté mais que les id ne correspondent pas
*/
public int detect_key() {
int retour = -1;
//Liste les fichiers racines
File[] drive = File.listRoots();
for (File path : drive) {
//on récupère le nom
String Key_Name = fsv.getSystemDisplayName(path);
// si le nom est KEY
if (Key_Name.lastIndexOf("KEY") != -1) {
// on récupère l'id de lecteur de travail sur le pc
String IdKeyPC = GetIdKey("C:\\");
// on récupère l'id de lecteur de travail sur le lecteur qui contient Key
String IdKey = GetIdKey(path.toString());
//Si sa correspond on retourne 1 et on enregistre le port de communication
if (IdKey.equals(IdKeyPC)) {
retour = 1;
this.Port = path.toString();
} else {
retour = 0;
}
}
}
return retour;
}
public String getPort() {
return Port;
}
}