esp8266 / Arduino

ESP8266 core for Arduino
GNU Lesser General Public License v2.1
16.06k stars 13.33k forks source link

POST to ESP8266HTTPUpdateServer requires authentication #4424

Closed Fonta closed 5 years ago

Fonta commented 6 years ago

I've created a custom submit form for uploading a .bin file. But when I POST to /update the page requests authentication, whatever I fill in, it won't accept it. Also using the library without username and password still requires to authenticate.

This is how I setup the library:

ESP8266WebServer webserver(80);
ESP8266HTTPUpdateServer httpUpdater;

const char* update_path = "/update";
const char* update_username = "admin";
const char* update_password = "admin";

void setup_webserver() {

  //setup webserver addresses
  webserver.on("/", web_returnRoot);
  webserver.on("/upload", web_updatePage);

  httpUpdater.setup(&webserver, update_path, update_username, update_password);
  webserver.begin();
}

And the page with the form is as follows:

void web_updatePage() {
  String message = "<html lang='en'><head><meta charset='utf-8'><meta name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no'><title>Doorbell Configuration</title>";
  message += "<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css' integrity='sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm' crossorigin='anonymous'>";
  message += "</head><body>";
  message += "<nav class='navbar navbar-expand-md navbar-dark bg-dark mb-4'><div class='container'><a href='/' class='navbar-brand'>Doorbell Configuration</a></div></nav>";
  message += "<main role='main' class='container'><div class='jumbotron'>";
  message += "<form id='data' action='/update' method='POST' enctype='multipart/form-data'>";
  message += "<div class='input-group mb-3'><div class='custom-file'><input type='file' accept='.bin' class='custom-file-input' id='inputGroupFile04' name='update'><label class='custom-file-label' for='inputGroupFile04'>Choose file</label></div><div class='input-group-append'><button class='btn btn-danger' type='submit'>Update!</button></div></div>";
  message += "<div class='form-group'><button type='button' class='btn btn-Primary' onclick='window.location.href=\"/\"'>Back</button></div>";
  message += "</form></div></main></body></html>";

  webserver.send(200, "text/html", message);
}

I've also tried to put authentication on the /upload page and authenticate with the username and password and then submitting a file. But it will still request authentication.

Is there anything I can do to make this form work? Image of the form

Fonta commented 6 years ago

I've created a PR: https://github.com/esp8266/Arduino/pull/4425 It might not be the best solution, but it does fix not being able to authenticate when I use a custom form.

Fonta commented 5 years ago

Nobody cares. Closing the issue.

arlaor commented 4 years ago

Hi @Fonta

I don't know if the issue applies to this problem, but I will ask. I have uploaded three pages html through FS.h to the memory of esp8266, among which is the page that updates the code of esp8266, but when calling the file .bin, it does not update the code of esp8266. What extra code should I write to get the update information of the page mounted in the ESP memory?

This is my code

#include <ESP8266HTTPUpdateServer.h>
#include <ESP8266WiFiMulti.h>
#include <WebSocketsServer.h>
#include <ESP8266mDNS.h>
#include <Hash.h>

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

#define DEBUG_SERIAL //uncomment for Serial debugging statements
#ifdef DEBUG_SERIAL
#define DEBUG_BEGIN Serial.begin(115200)
#define DEBUG_PRINT(x) Serial.println(x)
#else
#define DEBUG_PRINT(x)
#define DEBUG_BEGIN
#endif
//includes
#include <PersWiFiManager.h>
#include <ArduinoJson.h>
#include <EasySSDP.h> // http://ryandowning.net/EasySSDP/
//extension of ESP8266WebServer with SPIFFS handlers built in
#include <SPIFFSReadServer.h> // http://ryandowning.net/SPIFFSReadServer/
// upload data folder to chip with Arduino ESP8266 filesystem uploader
// https://github.com/esp8266/arduino-esp8266fs-plugin
#include <DNSServer.h>
#include <FS.h>
#define DEVICE_NAME "ESP8266 DEVICE"
//server objects
SPIFFSReadServer server(80);
DNSServer dnsServer;
PersWiFiManager persWM(server, dnsServer);

const char* host = "Light";
const char* update_path = "/update";
const char* update_username = "xx";
const char* update_password = "xxxxxxx";

IPAddress ip = WiFi.localIP(); // desired IP Address
IPAddress mask = WiFi.subnetMask(); //Mascara de red
IPAddress gat = WiFi.gatewayIP();//gateway

MDNSResponder mdns;
ESP8266WiFiMulti WiFiMulti;
ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;

void setup(void){

//******************perswifimanager CODE INI*****************
  DEBUG_BEGIN; //for terminal debugging
  DEBUG_PRINT();

  //optional code handlers to run everytime wifi is connected...
  persWM.onConnect([]() {
    DEBUG_PRINT("wifi connected");
    DEBUG_PRINT(ip);
    DEBUG_PRINT(gat);
    DEBUG_PRINT(mask);
    EasySSDP::begin(server);
  });
  //...or AP mode is started
  persWM.onAp([](){
    DEBUG_PRINT("AP MODE");
    DEBUG_PRINT(persWM.getApSsid());
  });

  //allows serving of files from SPIFFS
  SPIFFS.begin();
  //SPIFFS.format();
  //sets network name for AP mode
 // persWM.setApCredentials(DEVICE_NAME);
  persWM.setApCredentials(DEVICE_NAME, "password"); //optional password

  //make connecting/disconnecting non-blocking
  persWM.setConnectNonBlock(true);

  //in non-blocking mode, program will continue past this point without waiting
  persWM.begin();

This is the part of the page in the memory of the ESP8266

  server.serveStatic("/", SPIFFS, "/page1.html");
  server.serveStatic("/update", SPIFFS, "/update.html");
  server.serveStatic("/page3", SPIFFS, "/page3.html");

  server.begin();
  DEBUG_PRINT("setup complete.");

 httpServer.on("/", [](){
page = String(ldt); //publish the value in text
 httpServer.send(200, "text/html", page);
});
 httpServer.begin();
Serial.println("Web server started!");

    httpUpdater.setup(&httpServer, update_path, update_username, update_password);
    httpServer.onNotFound(handleNotFound);
 //   httpServer.begin();
}

void loop(void){
//*************perswifimanager CODE INI******************
  //in non-blocking mode, handleWiFi must be called in the main loop
  persWM.handleWiFi();

  dnsServer.processNextRequest();
  server.handleClient();

  //DEBUG_PRINT(millis());

  // do stuff with x and y
//************perswifimanager CODE END******************

ldt = analogRead(A0);
mov = digitalRead(D5);
Serial.println(ldt);
Serial.print("mvto ");
Serial.println(mov);
delay(1000);

 httpServer.handleClient();
}

void handleNotFound() {
  //  server.serveStatic("/page3", SPIFFS, "/page3.html");
  httpServer.send(404, "text/plain", "404: Not found");
}

This is the code in the page UPDATE.HTML

<!DOCTYPE html>
     <html lang='en'>
     <head>
         <meta charset='utf-8'>
         <meta name='viewport' content='width=device-width,initial-scale=1'/>
     </head>
     <body>
     <form method='POST' action='' enctype='multipart/form-data'>
         Firmware:<br>
         <input type='file' accept='.bin' name='firmware'>
         <input type='submit' value='Update Firmware'>
     </form>
     <form method='POST' action='' enctype='multipart/form-data'>
         FileSystem:<br>
         <input type='file' accept='.bin' name='filesystem'>
         <input type='submit' value='Update FileSystem'>
     </form>
        <a href="javascript:history.back()">Back</a> | 
        <a href="/">Home</a>
     </body>
     </html>
Fonta commented 4 years ago

Hi @arlaor

My quick guess would be that httpServer.begin(); has to be after httpUpdater.setup(&httpServer, update_path, update_username, update_password);.

Otherwise I don't really see anything.