Esp8266 commandes sécurisées ++

Bonsoir, j’ai fait un code pour sécuriser mes commandes et ajouté un
raccourci sur mon téléphone pour y accéder facilement. Mais si jamais
je l’oublie quelque part en mode déverrouillé, n’importe qui aurait accès
mes commandes. Mon cahier des charges est simple : si une personne appuie
sur le raccourci du téléphone pour accéder à mes commandes, une page de
connexion s’affiche, demandant un identifiant et un mot de passe.
Après trois tentatives échouées, l’accès à cette page sera bloqué et un
Gmail d’alerte sera envoyé à mon adresse Gmail. Pour réactiver l’accès aux
identifiants, il faudra utiliser un port différent du port principal, connu
que de moi, qui permettra de débloquer l’accès. Je souhaite aussi ajouter
une option 'Mot de passe oublié', Pour récupérer mes identifiants, il faudra
encore une fois utiliser un port différent des précédents connu que de moi.
Et pour finir il faudra une déconnexion possible de l'accès aux commandes .
Je laisse le code qui fonctionne parfaitement , je l'ai commenter au mieux.
Bonne soirée.

#include <ESP8266WiFi.h>     
#include <Base64.h> // je n'ai que cette librairie qui fonctionne pour l'envoi de gmail !

#define ssid      "xxxxxxxxxxxxx" // identifiant box
#define pass_word "xxxxxxxxxxxxx" // mot de passe box

const char* mailRecipient = "xxxxxxxxxx" ; // gmail destinataire
const char* mailUser      = "xxxxxxxxxx" ; // gmail expéditeur

// Validation en 2 étapes .
// Le code à 16 chiffre donné à copier coller ici ( voir la méthode sur le net )
const char* mailPassword  = "xxxx xxxx xxxx xxxx" ; // mot de passe d'application

const char* mailServer    = "smtp.gmail.com" ; // ne pas modifier

const char* Nom_d_utilisateur = "Arduino" ; // c'est ici que l'on choisi sont identifiant pour l'accès aux commandes
const char* Mot_de_passe      = "2025" ;    // c'est ici que l'on choisi sont mot de passe pour l'accès aux commandes

const int mailPort = 465 ; // ici laisser cette valeur

// Penser à faire une redirection de port dans l'OS de "freebox" pour un accès externe.
// accès externe == wifi tel désactivé --> données mobiles tel activées .
// Donc on se retrouve avec 3 redirections de ports avec le même esp8266.
// Pour la méthode voir sur le forum à "Projet ESP8266 maudit" 
const int port_principal       = 7680  ; // c'est le port principal.
const int port_de_reactivation = 1234  ; // c'est le port de réactivation de la page des identifiants.
const int port_de_restitution  = 5678  ; // c'est le port de rèstitution du mot de passe oublié.

WiFiClientSecure mailClient ;         

WiFiServer server ( 7680 ) ; // ici on est obligé de mettre 7680

int currentPort = port_principal ; 
bool isAuthenticated = false ;
int tentativesRestantes = 3 ;
int LED = D1 ;  // LED connectée au pin D1 de l'ESP8266

void toggleLED ( ) ;  // Fonction pour la bascule de la led
void sendAlertEmail ( ) ; // Fonction pour l'envoi de gmail

void setup ( )
{
Serial . begin ( 115200 ) ;
pinMode ( LED , OUTPUT ) ;  // Initialisation du pin D1 comme sortie
digitalWrite ( LED , LOW ) ;  // Éteindre la LED au démarrage

Serial . println ( ) ;
Serial . print ( "Connexion à " ) ;
Serial . println ( ssid ) ;
WiFi . begin ( ssid , pass_word ) ;

while ( WiFi . status ( ) != WL_CONNECTED )
{
delay ( 500 ) ;
Serial . print ( "." ) ;
}
Serial . println ( "\nWiFi connecté" ) ;
server . begin ( ) ;
Serial . println ( "Serveur Web lancé sur le port  " + String ( port_principal ) ) ;
}
void loop ( ) 
{
WiFiClient client = server . available ( ) ;
if ( client ) 
{
Serial . println ( "Nouveau client" ) ;
String header = "" ;
String currentLine = "" ;

while ( client . connected ( ) )
{
if ( client . available ( ) )
{
char c = client . read ( ) ;
header += c ;
if ( c == '\n' )
{
if ( currentLine . length ( ) == 0 )
{
// Section récupération du mot de passe :
if ( header . indexOf ( "GET /Authentification" ) >= 0 ) 
{
Serial . println ( "Passage au port " + String ( port_de_restitution ) + " pour la récupération du mot de passe !" ) ;
currentPort = port_de_restitution ; 
server . stop ( ) ;
server = WiFiServer ( port_de_restitution ) ; 
server . begin ( ) ;
break ; // On sort de la boucle pour éviter d'autres traitements
}
else if ( currentPort == port_de_restitution ) // Si on est déjà sur le "port_de_restitution"
{
afficherPageRecuperation ( client ) ;
break ;
}
// Section réactivation du port principal :               
if ( currentPort == port_de_reactivation ) 
{  
Serial . println ( "Réactivation du port " + String ( port_principal ) + " !" ) ;
currentPort = port_principal ; 
tentativesRestantes = 3 ;  // Réinitialisation correcte ici après redirection
server . stop ( ) ;
server = WiFiServer ( port_principal ) ; 
server . begin ( ) ;
  
// Section css html de la réactivation de la page d'identification :
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html><head><title>Réactivation</title>");
client.println("<style>");
client.println("body { font-family: Arial, sans-serif; text-align: center; margin: 0; padding: 0; display: flex; flex-direction: column; justify-content: center; height: 70vh; }"); // décalage vers le bas
client.println("h1 { font-size: 60px; margin-bottom: 30px; }");  // Taille ajustée et marge ajoutée
client.println("h2 { font-size: 40px; margin-top: 20px; }");  // Décalage uniforme sous le titre
client.println("</style>");
client.println("</head>");
client.println("<body>");
client.println("<h1>R&eacute;activation de la page des identifiants</h1>");
client.println("</body></html>");
break;
}
// Section se connecter :
if ( header . indexOf ( "POST /login") >= 0 ) 
{
String postData = "" ;
while ( client . available ( ) ) 
{
char c = client . read ( ) ;
postData += c ;
}
String username = "", password = "";
int usernameStart = postData.indexOf("username=");
int passwordStart = postData.indexOf("password=");

if (usernameStart >= 0 && passwordStart > usernameStart)
{
username = postData.substring(usernameStart + 9, postData.indexOf('&', usernameStart));
password = postData.substring(passwordStart + 9);
}
if (username == Nom_d_utilisateur && password == Mot_de_passe )
{
Serial . println ( "Authentification réussie" ) ;
isAuthenticated = true ;
tentativesRestantes = 3 ;  

// S'assurer que si le "port_de_reactivation" était actif, on repasse bien sur le "port_principal"
if ( currentPort == port_de_reactivation ) 
{
Serial . println ( "Retour au port " + String ( port_principal ) + " après authentification réussie !" ) ;
currentPort = port_principal ; 
server . stop ( ) ;
server = WiFiServer ( port_principal ) ; 
server . begin ( ) ;
}
client.println("HTTP/1.1 303 See Other");
client.println("Location: /");
client.println("Connection: close");
client.println();
} else {
tentativesRestantes-- ;
Serial.println("Authentification échouée");

// Section ou on passe au port de réactivation
if ( tentativesRestantes <= 0 )
{
Serial . println ( "Trop d'échecs ! Passage au port " + String ( port_de_reactivation ) + " !" ) ;
sendAlertEmail ( ) ;  // Envoi de l'email d'alerte 
currentPort = port_de_reactivation ; 
server . stop ( ) ;
server = WiFiServer ( port_de_reactivation ) ; 
server . begin ( ) ;

} else {
afficherPageLogin ( client , true , tentativesRestantes ) ;
}  }
// Section déconnexion:
} else if ( header . indexOf ( "GET /logout" ) >= 0 ) 
{
Serial . println ( "Déconnexion" ) ;
isAuthenticated = false ;
tentativesRestantes = 3 ;

client.println("HTTP/1.1 303 See Other");
client.println("Location: /");
client.println("Connection: close");
client.println();

// Section bascule de la led 
} else if ( isAuthenticated )
{
if ( header . indexOf ( "GET /toggle" ) >= 0 ) 
{
toggleLED ( ) ; // Appel de la fonction pour changer l'état de la LED
}
afficherPagePrincipale ( client ) ;
} else {
afficherPageLogin ( client , false , tentativesRestantes ) ;
}
header = "" ;
break ;
} else {
currentLine = "" ;
}
} else if ( c != '\r' ) 
{
currentLine += c ;
}  }  }
client . stop ( ) ;
Serial . println ( "Client déconnecté" ) ;
} }

// Section css html de la page des commandes :
void afficherPagePrincipale ( WiFiClient &client )
{
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<head><title>Contr&ocirc;le LED</title>");
client.println("<style>");
client.println("body { font-family: Arial, sans-serif; text-align: center; padding: 80px; background-color: #f0f0f0; }");
client.println("h1 { font-size: 72px; color: #333; margin-bottom: 50px; }");
client.println("h2 { font-size: 48px; color: #555; margin-bottom: 40px; }");
client.println("a.toggle { display: inline-block; width: 200px; height: 200px; background-color: blue; border-radius: 50%; margin: 20px 0; position: relative; border: none; }");
client.println("a.toggle::before { content: ''; display: block; width: 60px; height: 60px; background-color: white; border-radius: 50%; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }");
client.println("a.logout { margin-top: 80px; color: red; border-color: red; text-decoration: none; font-size: 45px; padding: 10px 20px; display: inline-block; border: 2px solid red; border-radius: 8px; }");
client.println("a.logout:hover { background-color: red; color: white; }");
client.println("</style>");
client.println("</head>");
client.println("<body>");
client.println("<h1>Contr&ocirc;le de la LED</h1>");
client.println("<h2>&Eacute;tat actuel : " + String(digitalRead(LED) == HIGH ? "Allum&eacute;e" : "&Eacute;teinte") + "</h2>");
client.println("<a href='/toggle' class='toggle'></a><br>");
client.println("<a href='/logout' class='logout'>Se d&eacute;connecter</a>");
client.println("</body>");
client.println("</html>");
}

// Section css et html de la page des identifiants :
void afficherPageLogin(WiFiClient &client, bool failed, int tentatives)
{
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<head><title>Connexion</title>");
client.println("<style>");
client.println("body { font-family: Arial, sans-serif; text-align: center; padding: 80px; background-color: #f0f0f0; }");
client.println("h1 { font-size: 72px; color: #333; margin-bottom: 50px; }");
client.println("form { display: inline-block; text-align: left; padding: 60px; border: 5px solid #ccc; border-radius: 20px; background-color: #ffffff; box-shadow: 0px 0px 25px rgba(0, 0, 0, 0.1); }");
client.println("label { font-size: 32px; margin-bottom: 25px; display: block; }");
client.println("input[type='text'], input[type='password'] { font-size: 32px; padding: 25px; margin-bottom: 50px; width: 100%; border-radius: 12px; border: 2px solid #ccc; box-sizing: border-box; }");
client.println("button { font-size: 32px; padding: 25px 50px; background-color: #4CAF50; color: white; border: none; border-radius: 12px; cursor: pointer; width: 100%; margin-top: 40px; }");
client.println("button:hover { background-color: #45a049; }");
client.println("</style>");
client.println("</head>");
client.println("<body>");

// Section css et html du décompte des essais :
if ( failed )
{
client.println("<h1>Authentification &eacute;chou&eacute;e</h1>");
if ( tentatives == 2 )
{
client.println("<p style='color: red; font-size: 50px;'>2 essais restants</p>");
} else if ( tentatives == 1 )
{
client.println("<p style='color: red; font-size: 60px;'>Dernier essai</p>");
} }

// Section css html de la page d'identification :
client.println("<h1>Authentification requise</h1>");
client.println("<form method='POST' action='/login'>");
client.println("<label for='username'>Nom d'utilisateur</label>");
client.println("<input type='text' id='username' name='username' required>");
client.println("<label for='password'>Mot de passe</label>");
client.println("<input type='password' id='password' name='password' required>");
client.println("<button type='submit'>Se connecter</button>");
client.println("</form>");
client.println("<p style='text-align: center; margin-top: 50px; font-size: 50px;'>");
client.println("<a href='/Authentification' style='color: red; text-decoration: none;'>Mot de passe oubli&eacute; ? </a>");
client.println("</p>");
client.println("</body></html>");
}

// section de récupération des identifiants :
void afficherPageRecuperation ( WiFiClient &client )
{
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<head><title>R&eacute;cup&eacute;ration du mot de passe</title>");
client.println("<style>");
client.println("body { font-family: Arial, sans-serif; text-align: center; padding: 80px; background-color: #f0f0f0; }");
client.println("h1 { font-size: 72px; color: #333; margin-bottom: 50px; }");
client.println("p { font-size: 40px; color: #555; }");
client.println("</style>");
client.println("</head>");
client.println("<body>");
client.println("<h1>Identifiants r&eacute;cup&eacute;r&eacute;s</h1>");
client.println("<p><strong>Nom d'utilisateur :</strong> " + String ( Nom_d_utilisateur ) + "</p>");  
client.println("<p><strong>Mot de passe :</strong> " + String ( Mot_de_passe ) + "</p>");  
client.println("</body></html>");

// Après avoir affiché la page de récupération , repasser au port "port_principal" .
Serial . println ( "Retour au port " + String ( port_principal ) + " après récupération du mot de passe !" ) ;
currentPort = port_principal ; 
server . stop ( ) ;
server = WiFiServer ( port_principal ) ; 
server . begin ( ) ;
}
// Section pour basculer l'état de la LED :
void toggleLED ( ) 
{
int ledState = digitalRead ( LED ) ;  // Lire l'état actuel de la LED
digitalWrite ( LED , ledState == HIGH ? LOW : HIGH ) ; // Inverser l'état de la LED
Serial . println ( "Changement de l'état de la LED" ) ;
}

// Section pour l'envoi de gmail :
void sendAlertEmail ( )
{
Serial . println ( "Tentative échouée : Envoi d'une alerte email..." ) ;

if ( !mailClient . connect ( mailServer , mailPort ) )
{
Serial . println ( "Échec de connexion au serveur mail !" ) ;
return ;
}
if (!getResponse()) return;

mailClient.println("EHLO gmail.com");
if (!getResponse()) return;

mailClient.println("auth login");
if (!getResponse()) return;

mailClient.println(base64::encode(mailUser));
if (!getResponse()) return;

mailClient.println(base64::encode(mailPassword));
if (!getResponse()) return;

mailClient.println("MAIL FROM: <" + String(mailUser) + ">");
if (!getResponse()) return;

mailClient.println("RCPT TO: <" + String(mailRecipient) + ">");
if (!getResponse()) return;

mailClient.println("DATA");
if (!getResponse()) return;

mailClient.println("To: " + String(mailRecipient));
mailClient.println("From: " + String(mailUser));
mailClient.println("Subject: ALERTE ! ACCÈS BLOQUÉ \r\n");
mailClient.println("Attention ! \r\n");
mailClient.println("La page d'identification d'accès aux commandes vient d'être BLOQUÉE.\r\n");
mailClient.println(".");
if ( !getResponse ( ) ) return ;

mailClient . println ( "QUIT" ) ;
getResponse ( ) ;
mailClient . stop ( ) ;
Serial . println ( "Email d'alerte envoyé !" ) ;
}
// Section getResponse()attend une réponse du serveur après l'envoi d'une
// commande,affiche cette réponse sur le moniteur série et retourne 1 si 
// une réponse est reçue ou 0 en cas de dépassement du délai :
byte getResponse ( )
{
int timeout = 6000 , counter = 0 ; 
while ( !mailClient . available ( ) )
{
delay ( 1 ) ;
if ( ++counter > timeout )
{
Serial . println ( "Timeout" ) ;
mailClient . stop ( ) ;
return 0 ;
} }
while ( mailClient.available()) Serial.write(mailClient.read());
return 1 ;
} 

Salut!

C'est la partie internationale du forum, si vous écrivez en anglais nous pouvons vous aider ici. Sinon, il y a aussi une section française. J'espère que votre question recevra une réponse satisfaisante. :slightly_smiling_face:

Bonne nuit!

je ne sais pas publié sur le site en français dsl bonne soirée.

MERCI mon ami.

Veuillez utiliser la langue anglaise dans les sections anglaises du forum. Votre sujet a été déplacé vers la section française du forum.

Ça fait mal au crâne de lire un code qui n'est pas indenté...

Pour indenter le code correctement dans l'IDE avant de le copier pour le coller ici, cela se fait en pressant ctrlT sur PC ou cmdT sur un Mac...