Note de ce sujet :
  • Moyenne : 0 (0 vote(s))
  • 1
  • 2
  • 3
  • 4
  • 5
Sécuriser l' accès des pages du serveur
#1
Bonjour 

Ma demande à Gemini pro avec le fichier server ino v15.10:


Sécuriser l accès des pages par basic auth, et ajoute du code pour pouvoir modifier mot de passe, donne le fichier entièrement modifié

(Il demande une fois le mot de passe pour l'accès à l'ensemble des pages tant que la session est ouverte, IMPORTANT : Vous devez ajouter ces variables à vos fonctions de lecture/écriture ROM
// (comme EcritureEnROM) pour les sauvegarder de manière permanente !!
String www_user = "admin";
String www_pass = "admin"Wink



// ***************
// * WEB SERVER *
// ***************
[span_0](start_span)bool opened = false;[span_0](end_span)
[span_1](start_span)String ConfImport;[span_1](end_span)

// --- AJOUT POUR BASIC AUTH ---
// Identifiants par défaut.
// !! IMPORTANT : Vous devez ajouter ces variables à vos fonctions de lecture/écriture ROM
// (comme EcritureEnROM) pour les sauvegarder de manière permanente !!
String www_user = "admin";
String www_pass = "admin";

// Page HTML pour changer le mot de passe
const char PassHtml[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html><head>
<title>Changer Mot de Passe</title><meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<style>
  body { font-family: Arial, sans-serif; background: #f0f0f0; text-align: center; }
  div { background: #fff; border-radius: 8px; padding: 20px; max-width: 400px; margin: 50px auto; box-shadow: 0 4px 8px rgba(0,0,0,0.1); }
  input { width: 90%; padding: 10px; margin: 10px 0; border: 1px solid #ccc; border-radius: 4px; }
  button { background: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }
  button:hover { background: #0056b3; }
</style>
</head><body>
<div>
  <h2>Changer le mot de passe</h2>
  <form action='/passupdate' method='POST'>
    Nom d'utilisateur:<br>
    <input type='text' name='user' value='@@USER@@'><br>
    Nouveau mot de passe:<br>
    <input type='password' name='pass'><br>
    <button type='submit'>Enregistrer</button>
  </form>
  <br><a href='/'>Retour</a>
</div>
</body></html>
)rawliteral";


/**
 * @brief Vérifie l'authentification "Basic Auth".
 * Renvoie 'true' si l'utilisateur est authentifié (ou en mode AP).
 * Renvoie 'false' si l'authentification a échoué et demande les identifiants.
 */
bool checkAuth() {
  // Désactive l'authentification en mode AP pour permettre la configuration Wi-Fi
  if (WiFi.getMode() != WIFI_STA) {
    return true;
  }
  
  if (!server.authenticate(www_user.c_str(), www_pass.c_str())) {
    server.requestAuthentication();
    return false;
  }
  return true;
}
// --- FIN AJOUT BASIC AUTH ---


[span_2](start_span)void Init_Server() {[span_2](end_span)
  //Init Web Server on port 80
  [span_3](start_span)server.on("/", handleRoot);[span_3](end_span)
  [span_4](start_span)server.on("/MainJS", handleMainJS);[span_4](end_span)
  [span_5](start_span)server.on("/MainJS2", handleMainJS2);[span_5](end_span)
  [span_6](start_span)server.on("/MainJS3", handleMainJS3);[span_6](end_span)
  [span_7](start_span)server.on("/Para", handlePara);[span_7](end_span)
  [span_8](start_span)server.on("/ParaJS", handleParaJS);[span_8](end_span)
  [span_9](start_span)server.on("/ParaRouteurJS", handleParaRouteurJS);[span_9](end_span)
  [span_10](start_span)server.on("/ParaAjax", handleParaAjax);[span_10](end_span)
  [span_11](start_span)server.on("/ParaRouteurAjax", handleParaRouteurAjax);[span_11](end_span)
  [span_12](start_span)server.on("/ParaUpdate", handleParaUpdate);[span_12](end_span)
  [span_13](start_span)server.on("/Actions", handleActions);[span_13](end_span)
  [span_14](start_span)server.on("/ActionsJS", handleActionsJS);[span_14](end_span)
  [span_15](start_span)server.on("/ActionsJS2", handleActionsJS2);[span_15](end_span)
  [span_16](start_span)server.on("/ActionsJS3", handleActionsJS3);[span_16](end_span)
  [span_17](start_span)server.on("/ActionsUpdate", handleActionsUpdate);[span_17](end_span)
  [span_18](start_span)server.on("/ActionsAjax", handleActionsAjax);[span_18](end_span)
  [span_19](start_span)server.on("/Brute", handleBrute);[span_19](end_span)
  [span_20](start_span)server.on("/BruteJS", handleBruteJS);[span_20](end_span)
  [span_21](start_span)server.on("/BruteJS2", handleBruteJS2);[span_21](end_span)
  [span_22](start_span)server.on("/ajax_histo48h", handleAjaxHisto48h);[span_22](end_span)
  [span_23](start_span)server.on("/ajax_histo1an", handleAjaxHisto1an);[span_23](end_span)
  [span_24](start_span)server.on("/ajax_dataRMS", handleAjaxRMS);[span_24](end_span)
  [span_25](start_span)server.on("/ajax_dataESP32", handleAjaxESP32);[span_25](end_span)
  [span_26](start_span)server.on("/ajax_data", handleAjaxData);[span_26](end_span)
  [span_27](start_span)server.on("/ajax_data10mn", handleAjaxData10mn);[span_27](end_span)
  [span_28](start_span)server.on("/ajax_etatActions", handleAjax_etatActions);[span_28](end_span)
  [span_29](start_span)server.on("/ajax_etatActionX", handleAjax_etatActionX);[span_29](end_span)
  [span_30](start_span)server.on("/ajax_Temperature", handleAjaxTemperature);[span_30](end_span)
  [span_31](start_span)server.on("/ajax_Noms", handleAjaxNoms);[span_31](end_span)
  [span_32](start_span)server.on("/ajaxRAZhisto", handleajaxRAZhisto);[span_32](end_span)
  [span_33](start_span)server.on("/SetGPIO", handleSetGpio);[span_33](end_span)
  [span_34](start_span)server.on("/Export", handleExport);[span_34](end_span)
  [span_35](start_span)server.on("/export_file", handleExport_file);[span_35](end_span)
  [span_36](start_span)server.on("/restart", handleRestart);[span_36](end_span)
  [span_37](start_span)server.on("/Change_Wifi", handleChange_Wifi);[span_37](end_span)
  [span_38](start_span)server.on("/AP_ScanWifi", handleAP_ScanWifi);[span_38](end_span)
  [span_39](start_span)server.on("/AP_SetWifi", handleAP_SetWifi);[span_39](end_span)
  [span_40](start_span)server.on("/commun.css", handleCommunCSS);[span_40](end_span)

  // --- AJOUT ROUTES MOT DE PASSE ---
  server.on("/password", handlePassword);
  server.on("/passupdate", HTTP_POST, handlePassUpdate); // Accepte le POST du formulaire

  [span_41](start_span)server.onNotFound(handleNotFound);[span_41](end_span)

  //SERVER OTA
  server.on("/OTA", HTTP_GET, []() {
    if (!checkAuth()) return; // <-- SÉCURISÉ
    server.sendHeader("Connection", "close");
    server.send(200, "text/html", OtaHtml);
  [span_42](start_span)});[span_42](end_span)
  /*handling uploading firmware file */
  server.on(
    "/update", HTTP_POST, []() {
      if (!checkAuth()) return; // <-- SÉCURISÉ (Partie 1)
      server.sendHeader("Connection", "close");
      server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
      ESP.restart();
    },
    []() {
      if (!checkAuth()) return; // <-- SÉCURISÉ (Partie 2)
      HTTPUpload& upload = server.upload();
      [span_43](start_span)if (upload.status == UPLOAD_FILE_START) {[span_43](end_span)
        [span_44](start_span)Serial.printf("Update: %s\n", upload.filename.c_str());[span_44](end_span)
        [span_45](start_span)if (!Update.begin(UPDATE_SIZE_UNKNOWN)) {[span_45](end_span)
          [span_46](start_span)Update.printError(Serial);[span_46](end_span)
        }
      [span_47](start_span)} else if (upload.status == UPLOAD_FILE_WRITE) { [cite: 246-247]
        /* flashing firmware to ESP*/
        [cite_start]if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {[span_47](end_span)
          [span_48](start_span)Update.printError(Serial);[span_48](end_span)
        }
      [span_49](start_span)} else if (upload.status == UPLOAD_FILE_END) {[span_49](end_span)
        [span_50](start_span)if (Update.end(true)) {[span_50](end_span)
          [span_51](start_span)Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);[span_51](end_span)
        } else {
          [span_52](start_span)Update.printError(Serial);[span_52](end_span)
        }
      }
    [span_53](start_span)});[span_53](end_span)

  /*handling uploading file */
  server.on(
    "/import", HTTP_POST, []() {
      if (!checkAuth()) return; // <-- SÉCURISÉ (Partie 1)
      server.sendHeader("Connection", "close");
      server.send(200, "text/plain", "OK");
    },
    []() {
      if (!checkAuth()) return; // <-- SÉCURISÉ (Partie 2)
      HTTPUpload& upload = server.upload();
      [span_54](start_span)if (opened == false) {[span_54](end_span)
        [span_55](start_span)opened = true;[span_55](end_span)

        [span_56](start_span)Serial.println("Debut Upload");[span_56](end_span)
        [span_57](start_span)ConfImport = "";[span_57](end_span)
      }
      [span_58](start_span)if (upload.status == UPLOAD_FILE_WRITE) {[span_58](end_span)
        [span_59](start_span)for (int i = 0; i < upload.currentSize; i++) { [cite: 248-249]
          [cite_start]ConfImport += String(char(upload.buf[i]));[span_59](end_span)
        }
      [span_60](start_span)} else if (upload.status == UPLOAD_FILE_END) {[span_60](end_span)
        [span_61](start_span)Serial.println("UPLOAD_FILE_END");[span_61](end_span)
        [span_62](start_span)Serial.println(ConfImport);[span_62](end_span)
        [span_63](start_span)ImportParametres(ConfImport);[span_63](end_span)
        [span_64](start_span)opened = false;[span_64](end_span)
      }
    [span_65](start_span)});[span_65](end_span)
  [span_66](start_span)server.begin();[span_66](end_span)
}

// --- NOUVEAUX HANDLERS POUR MOT DE PASSE ---

/**
 * @brief Affiche la page de modification du mot de passe.
 */
void handlePassword() {
  if (!checkAuth()) return; // Sécurise l'accès à cette page
  String html = PassHtml;
  html.replace("@@USER@@", www_user);
  server.sendHeader("Connection", "close");
  server.send(200, "text/html", html);
}

/**
 * @brief Traite la mise à jour du mot de passe depuis le formulaire.
 */
void handlePassUpdate() {
  if (!checkAuth()) return; // Sécurise l'accès à cette fonction
  
  if (server.hasArg("user") && server.hasArg("pass")) {
    www_user = server.arg("user");
    www_pass = server.arg("pass");
    
    // !! IMPORTANT !!
    // Assurez-vous que votre fonction EcritureEnROM() (dans votre .ino principal)
    // sauvegarde bien les variables 'www_user' et 'www_pass' en EEPROM.
    EcritureEnROM(); [span_67](start_span)// Appel de votre fonction existante[span_67](end_span)
    
    server.sendHeader("Connection", "close");
    server.send(200, "text/plain", "OK. Mot de passe mis a jour. Le navigateur va redemander l'authentification.");
  } else {
    server.sendHeader("Connection", "close");
    server.send(400, "text/plain", "Erreur: 'user' ou 'pass' manquant.");
  }
}

// --- HANDLERS EXISTANTS (TOUS MODIFIÉS AVEC checkAuth()) ---

void handleRoot() { //Pages principales
  if (!checkAuth()) return; // <-- SÉCURISÉ

  [span_68](start_span)server.sendHeader("Connection", "close");[span_68](end_span)
  [span_69](start_span)if (WiFi.getMode() != WIFI_STA) {[span_69](end_span)
    [span_70](start_span)server.send(200, "text/html", ConnectAP_Html);[span_70](end_span)
  } else {
    [span_71](start_span)server.send(200, "text/html", MainHtml);[span_71](end_span)
  }
}
void handleChange_Wifi() {
  if (!checkAuth()) return; // <-- SÉCURISÉ
  [span_72](start_span)server.sendHeader("Connection", "close");[span_72](end_span)
  [span_73](start_span)server.send(200, "text/html", ConnectAP_Html);[span_73](end_span)
}
void handleMainJS() { //Code Javascript
  if (!checkAuth()) return; // <-- SÉCURISÉ
  [span_74](start_span)server.sendHeader("Connection", "close");[span_74](end_span)
  [span_75](start_span)server.send(200, "text/javascript", MainJS);[span_75](end_span)
}
void handleMainJS2() { //Code Javascript
  if (!checkAuth()) return; // <-- SÉCURISÉ
  [span_76](start_span)server.sendHeader("Connection", "close");[span_76](end_span)
  [span_77](start_span)server.send(200, "text/javascript", MainJS2);[span_77](end_span)
}
void handleMainJS3() { //Code Javascript
  if (!checkAuth()) return; // <-- SÉCURISÉ
  [span_78](start_span)server.sendHeader("Connection", "close");[span_78](end_span)
  [span_79](start_span)server.send(200, "text/javascript", MainJS3);[span_79](end_span)
}
void handleBrute() { //Page données brutes
  if (!checkAuth()) return; // <-- SÉCURISÉ
  [span_80](start_span)server.sendHeader("Connection", "close");[span_80](end_span)
  [span_81](start_span)server.send(200, "text/html", PageBrute);[span_81](end_span)
}
void handleBruteJS() { //Code Javascript
  if (!checkAuth()) return; // <-- SÉCURISÉ
  [span_82](start_span)server.sendHeader("Connection", "close");[span_82](end_span)
  [span_83](start_span)server.send(200, "text/javascript", PageBruteJS);[span_83](end_span)
}
void handleBruteJS2() { //Code Javascript
  if (!checkAuth()) return; // <-- SÉCURISÉ
  [span_84](start_span)server.sendHeader("Connection", "close");[span_84](end_span)
  [span_85](start_span)server.send(200, "text/javascript", PageBruteJS2);[span_85](end_span)
}

void handleAjaxRMS() { // Envoi des dernières données brutes reçues du RMS
  if (!checkAuth()) return; // <-- SÉCURISÉ
  [span_86](start_span)String S = "";[span_86](end_span)
  [span_87](start_span)String RMSExtDataB = "";[span_87](end_span)
  [span_88](start_span)int LastIdx = server.arg(0).toInt();[span_88](end_span)
  [span_89](start_span)if (Source == "Ext") {[span_89](end_span)
    [span_90](start_span)WiFiClient clientESP_RMS;[span_90](end_span)
    [span_91](start_span)String host = IP2String(RMSextIP);[span_91](end_span)
    [span_92](start_span)if (!clientESP_RMS.connect(host.c_str(), 80)) {[span_92](end_span)
      [span_93](start_span)StockMessage("connection to ESP_RMS external failed (call from handleAjaxRMS)");[span_93](end_span)
      [span_94](start_span)return;[span_94](end_span)
    }
    [span_95](start_span)String url = "/ajax_dataRMS?idx=" + String(LastIdx);[span_95](end_span)
    [span_96](start_span)clientESP_RMS.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n");[span_96](end_span)
    [span_97](start_span)unsigned long timeout = millis();[span_97](end_span)
    [span_98](start_span)while (clientESP_RMS.available() == 0) {[span_98](end_span)
      [span_99](start_span)if (millis() - timeout > 5000) {[span_99](end_span)
        [span_100](start_span)StockMessage(">>> clientESP_RMS Timeout !");[span_100](end_span)
        [span_101](start_span)clientESP_RMS.stop();[span_101](end_span)
        [span_102](start_span)return;[span_102](end_span)
      }
    }
    [span_103](start_span)while (clientESP_RMS.available()) {[span_103](end_span)
      [span_104](start_span)RMSExtDataB += clientESP_RMS.readStringUntil('\r');[span_104](end_span)
    }
    [span_105](start_span)S = RMSExtDataB.substring(RMSExtDataB.indexOf("\n\n") + 2);[span_105](end_span)
  } else {
    [span_106](start_span)S = DATE + RS + Source_data;[span_106](end_span)
    [span_107](start_span)if (Source_data == "UxI") {[span_107](end_span)
      [span_108](start_span)S += RS + String(Tension_M) + RS + String(Intensite_M) + RS + String(PowerFactor_M) + GS;[span_108](end_span)
      [span_109](start_span)int i0 = 0;[span_109](end_span)
      [span_110](start_span)int i1 = 0;[span_110](end_span)
      [span_111](start_span)for (int i = 0; i < 100; i++) {[span_111](end_span)
        [span_112](start_span)i1 = (i + 1) % 100;[span_112](end_span)
        [span_113](start_span)if (voltM[i] <= 0 && voltM[i1] > 0) {[span_113](end_span)
          [span_114](start_span)i0 = i1;[span_114](end_span)
          [span_115](start_span)i = 100;[span_115](end_span)
        }
      }
      [span_116](start_span)for (int i = 0; i < 100; i++) {[span_116](end_span)
        [span_117](start_span)i1 = (i + i0) % 100;[span_117](end_span)
        [span_118](start_span)S += String(int(10 * voltM[i1])) + RS;[span_118](end_span)
      }
      [span_119](start_span)S += "0" + GS;[span_119](end_span)
      [span_120](start_span)for (int i = 0; i < 100; i++) {[span_120](end_span)
        [span_121](start_span)i1 = (i + i0) % 100;[span_121](end_span)
        [span_122](start_span)S += String(int(10 * ampM[i1])) + RS;[span_122](end_span)
      }
      [span_123](start_span)S += "0";[span_123](end_span)
    }
    [span_124](start_span)if (Source_data == "UxIx2") {[span_124](end_span)
      [span_125](start_span)S += GS + String(Tension_M) + RS + String(Intensite_M) + RS + String(PuissanceS_M - PuissanceI_M) + RS + String(PowerFactor_M) + RS + String(Energie_M_Soutiree) + RS + String(Energie_M_Injectee);[span_125](end_span)
      [span_126](start_span)S += RS + String(Tension_T) + RS + String(Intensite_T) + RS + String(PuissanceS_T - PuissanceI_T) + RS + String(PowerFactor_T) + RS + String(Energie_T_Soutiree) + RS + String(Energie_T_Injectee);[span_126](end_span)
      [span_127](start_span)S += RS + String(Frequence);[span_127](end_span)
    }
    [span_128](start_span)if (Source_data == "Linky") {[span_128](end_span)
      [span_129](start_span)S += GS;[span_129](end_span)
      [span_130](start_span)while (LastIdx != IdxDataRawLinky) {[span_130](end_span)
        [span_131](start_span)S += String(DataRawLinky[LastIdx]);[span_131](end_span)
        [span_132](start_span)LastIdx = (1 + LastIdx) % 10000;[span_132](end_span)
      }
      [span_133](start_span)S += GS + String(IdxDataRawLinky);[span_133](end_span)
    }
    [span_134](start_span)if (Source_data == "Enphase") {[span_134](end_span)
      [span_135](start_span)S += GS + String(Tension_M) + RS + String(Intensite_M) + RS + String(PuissanceS_M - PuissanceI_M) + RS + String(PowerFactor_M) + RS + String(Energie_M_Soutiree) + RS + String(Energie_M_Injectee);[span_135](end_span)
      [span_136](start_span)S += RS + String(PactProd) + RS + String(PactConso_M);[span_136](end_span)
      [span_137](start_span)String SessionId = "Not Received from Enphase";[span_137](end_span)
      [span_138](start_span)if (Session_id != "") {[span_138](end_span)
        [span_139](start_span)SessionId = "Ok Received from Enphase";[span_139](end_span)
      }
      [span_140](start_span)String Token_Enphase = "Not Received from Enphase";[span_140](end_span)
      [span_141](start_span)if (TokenEnphase.length() > 50) {[span_141](end_span)
        [span_142](start_span)Token_Enphase = "Ok Received from Enphase";[span_142](end_span)
      }
      [span_143](start_span)if (EnphaseUser == "") {[span_143](end_span)
        [span_144](start_span)SessionId = "Not Requested";[span_144](end_span)
        [span_145](start_span)Token_Enphase = "Not Requested";[span_145](end_span)
      }
      [span_146](start_span)S += RS + SessionId;[span_146](end_span)
      [span_147](start_span)S += RS + Token_Enphase;[span_147](end_span)
    }
    [span_148](start_span)if (Source_data == "SmartG") {[span_148](end_span)
      [span_149](start_span)S += GS + SG_dataBrute;[span_149](end_span)
    }
    [span_150](start_span)if (Source_data == "ShellyEm" || Source_data == "ShellyPro") {[span_150](end_span)
      [span_151](start_span)S += GS + ShEm_dataBrute;[span_151](end_span)
    }
    [span_152](start_span)if (Source_data == "UxIx3") {[span_152](end_span)
      [span_153](start_span)S += GS + MK333_dataBrute;[span_153](end_span)
    }
    [span_154](start_span)if (Source_data == "Pmqtt") {[span_154](end_span)
      [span_155](start_span)S += GS + P_MQTT_Brute;[span_155](end_span)
    }
  }
  [span_156](start_span)server.sendHeader("Connection", "close");[span_156](end_span)
  [span_157](start_span)server.send(200, "text/html", S);[span_157](end_span)
}
void handleAjaxHisto48h() { // Envoi Historique de 50h (600points) toutes les 5mn
  if (!checkAuth()) return; // <-- SÉCURISÉ
  [span_158](start_span)String S = "";[span_158](end_span)
  [span_159](start_span)String T = "";[span_159](end_span)
  [span_160](start_span)String U = "";[span_160](end_span)
  [span_161](start_span)String Ouverture = "";[span_161](end_span)
  [span_162](start_span)int iS = IdxStockPW;[span_162](end_span)
  [span_163](start_span)for (int i = 0; i < 600; i++) {[span_163](end_span)
    [span_164](start_span)S += String(tabPw_Maison_5mn[iS]) + ",";[span_164](end_span)
    [span_165](start_span)T += String(tabPw_Triac_5mn[iS]) + ",";[span_165](end_span)
    [span_166](start_span)iS = (1 + iS) % 600;[span_166](end_span)
  }
  [span_167](start_span)for (int canal = 0; canal < 4; canal++) {[span_167](end_span)
    [span_168](start_span)iS = IdxStockPW;[span_168](end_span)
    [span_169]}
Esp32 wroom avec ui2 et Ssr en 12.06 modifié
 pas de PV
Répondre

#2
En affinant la question on peut demander le mot de passe que en dehors du wi-fi réseau local (au cas où ça bloquerait le dialogue entre les ESP et ça facilite la connexion chez soi)
Esp32 wroom avec ui2 et Ssr en 12.06 modifié
 pas de PV
Répondre

#3
Je ne souhaite pas protéger toutes les pages, mais uniquement les pages de paramétrages comme cela est fait actuellement. Cela évite de rentrer le mot de passe chaque fois que l'on jette un coup d'œil sur le fonctionnement du routeur.

Comme nous ne sommes pas en https, même avec la méthode que vous proposez, les mots de passe sont visibles par quelqu'un de malveillant scrutant la ligne.

Pourquoi en faire plus, le plaisir de modifier les réglages du routeur ?

Cdlt
André
Répondre



Atteindre :


Utilisateur(s) parcourant ce sujet :
1 visiteur(s)

Moteur MyBB, © 2002-2025 Melroy van den Berg.