[WebUI] Added Basic Authentication (#1618)
* [WebUI] Added Basic Authentication * Make the security option a MACRO to avoid typos in future updates
This commit is contained in:
1 parent
abeef870c7
commit
acc0d91ca8
5 files changed
+148
-29
No files matched your search
+78
-24
@@ -45,22 +45,6 @@ QueueHandle_t webUIQueue;
|
||||
|
||||
WebServer server(80);
|
||||
|
||||
boolean displayMetric = DISPLAY_METRIC;
|
||||
|
||||
/*------------------- Local functions ----------------------*/
|
||||
|
||||
void notFound();
|
||||
void handleRoot(); // "/"
|
||||
|
||||
void handleCS(); // Console
|
||||
void handleCN(); // Configuration
|
||||
|
||||
void handleIN(); // Information
|
||||
|
||||
void handleRT(); // Restart
|
||||
void handleCL(); // Configure Cloud
|
||||
void handleTK(); // Return Cloud token
|
||||
|
||||
/*------------------- External functions ----------------------*/
|
||||
|
||||
esp_err_t nvs_flash_erase(void);
|
||||
@@ -81,7 +65,11 @@ const uint16_t TOPSZ = 151; // Max number of characters in topic string
|
||||
uint8_t masterlog_level; // Master log level used to override set log level
|
||||
bool reset_web_log_flag = false; // Reset web console log
|
||||
|
||||
# ifdef ESP32
|
||||
const char* www_username = WEBUI_LOGIN;
|
||||
String authFailResponse = "Authentication Failed";
|
||||
bool webUISecure = WEBUI_AUTH;
|
||||
boolean displayMetric = DISPLAY_METRIC;
|
||||
|
||||
/*********************************************************************************************\
|
||||
* ESP32 AutoMutex
|
||||
\*********************************************************************************************/
|
||||
@@ -241,8 +229,6 @@ String HtmlEscape(const String unescaped) {
|
||||
return result;
|
||||
}
|
||||
|
||||
# endif // ESP32
|
||||
|
||||
void AddLogData(uint32_t loglevel, const char* log_data, const char* log_data_payload = nullptr, const char* log_data_retained = nullptr) {
|
||||
// Store log_data in buffer
|
||||
// To lower heap usage log_data_payload may contain the payload data from MqttPublishPayload()
|
||||
@@ -414,6 +400,7 @@ bool exists(String path) {
|
||||
*/
|
||||
void handleRoot() {
|
||||
WEBUI_TRACE_LOG(F("handleRoot: uri: %s, args: %d, method: %d" CR), server.uri(), server.args(), server.method());
|
||||
WEBUI_SECURE
|
||||
if (server.args()) {
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
WEBUI_TRACE_LOG(F("Arg: %d, %s=%s" CR), i, server.argName(i).c_str(), server.arg(i).c_str());
|
||||
@@ -476,6 +463,7 @@ void handleRoot() {
|
||||
*
|
||||
*/
|
||||
void handleCN() {
|
||||
WEBUI_SECURE
|
||||
WEBUI_TRACE_LOG(F("handleCN: uri: %s, args: %d, method: %d" CR), server.uri(), server.args(), server.method());
|
||||
if (server.args()) {
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
@@ -499,6 +487,54 @@ void handleCN() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief /WU - Configuration Page
|
||||
* T: handleWU: uri: /wu, args: 3, method: 1
|
||||
* T: handleWU Arg: 0, dm=on - displayMetric
|
||||
* T: handleWU Arg: 1, sw=on - webUISecure
|
||||
* T: handleWU Arg: 2, save=
|
||||
*/
|
||||
void handleWU() {
|
||||
WEBUI_TRACE_LOG(F("handleWU: uri: %s, args: %d, method: %d" CR), server.uri(), server.args(), server.method());
|
||||
WEBUI_SECURE
|
||||
if (server.args()) {
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
WEBUI_TRACE_LOG(F("handleWU Arg: %d, %s=%s" CR), i, server.argName(i).c_str(), server.arg(i).c_str());
|
||||
}
|
||||
bool update = false;
|
||||
|
||||
if (displayMetric != server.hasArg("dm")) {
|
||||
update = true;
|
||||
}
|
||||
displayMetric = server.hasArg("dm");
|
||||
|
||||
if (webUISecure != server.hasArg("sw")) {
|
||||
update = true;
|
||||
}
|
||||
webUISecure = server.hasArg("sw");
|
||||
|
||||
if (server.hasArg("save") && update) {
|
||||
WebUIConfig_save();
|
||||
}
|
||||
}
|
||||
|
||||
char jsonChar[100];
|
||||
serializeJson(modules, jsonChar, measureJson(modules) + 1);
|
||||
|
||||
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE];
|
||||
|
||||
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Configure WebUI").c_str());
|
||||
String response = String(buffer);
|
||||
response += String(script);
|
||||
response += String(style);
|
||||
int logLevel = Log.getLevel();
|
||||
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_webui_body, jsonChar, gateway_name, (displayMetric ? "checked" : ""), (webUISecure ? "checked" : ""));
|
||||
response += String(buffer);
|
||||
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
|
||||
response += String(buffer);
|
||||
server.send(200, "text/html", response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief /WI - Configure WiFi Page
|
||||
* T: handleWI: uri: /wi, args: 4, method: 1
|
||||
@@ -508,6 +544,7 @@ void handleCN() {
|
||||
*/
|
||||
void handleWI() {
|
||||
WEBUI_TRACE_LOG(F("handleWI: uri: %s, args: %d, method: %d" CR), server.uri(), server.args(), server.method());
|
||||
WEBUI_SECURE
|
||||
String WiFiScan = "";
|
||||
if (server.args()) {
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
@@ -670,6 +707,7 @@ void handleWI() {
|
||||
*/
|
||||
void handleMQ() {
|
||||
WEBUI_TRACE_LOG(F("handleMQ: uri: %s, args: %d, method: %d" CR), server.uri(), server.args(), server.method());
|
||||
WEBUI_SECURE
|
||||
if (server.args()) {
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
WEBUI_TRACE_LOG(F("handleMQ Arg: %d, %s=%s" CR), i, server.argName(i).c_str(), server.arg(i).c_str());
|
||||
@@ -708,10 +746,10 @@ void handleMQ() {
|
||||
}
|
||||
|
||||
// SC - Secure Connection argument is only present when true
|
||||
WEBtoSYS["mqtt_secure"] = server.hasArg("sc");
|
||||
if (mqtt_secure != server.hasArg("sc")) {
|
||||
update = true;
|
||||
}
|
||||
WEBtoSYS["mqtt_secure"] = server.hasArg("sc");
|
||||
|
||||
if (!update) {
|
||||
Log.warning(F("[WebUI] clearing" CR));
|
||||
@@ -792,6 +830,7 @@ void handleMQ() {
|
||||
*/
|
||||
void handleLO() {
|
||||
WEBUI_TRACE_LOG(F("handleLO: uri: %s, args: %d, method: %d" CR), server.uri(), server.args(), server.method());
|
||||
WEBUI_SECURE
|
||||
if (server.args()) {
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
WEBUI_TRACE_LOG(F("handleLO Arg: %d, %s=%s" CR), i, server.argName(i).c_str(), server.arg(i).c_str());
|
||||
@@ -825,6 +864,7 @@ void handleLO() {
|
||||
*/
|
||||
void handleRT() {
|
||||
WEBUI_TRACE_LOG(F("handleRT: uri: %s, args: %d, method: %d" CR), server.uri(), server.args(), server.method());
|
||||
WEBUI_SECURE
|
||||
if (server.args()) {
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
WEBUI_TRACE_LOG(F("handleRT Arg: %d, %s=%s" CR), i, server.argName(i).c_str(), server.arg(i).c_str());
|
||||
@@ -862,6 +902,7 @@ void handleRT() {
|
||||
*/
|
||||
void handleCL() {
|
||||
WEBUI_TRACE_LOG(F("handleCL: uri: %s, args: %d, method: %d" CR), server.uri(), server.args(), server.method());
|
||||
WEBUI_SECURE
|
||||
if (server.args()) {
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
WEBUI_TRACE_LOG(F("handleCL Arg: %d, %s=%s" CR), i, server.argName(i).c_str(), server.arg(i).c_str());
|
||||
@@ -915,6 +956,7 @@ void handleCL() {
|
||||
*/
|
||||
void handleTK() {
|
||||
WEBUI_TRACE_LOG(F("handleTK: uri: %s, args: %d, method: %d" CR), server.uri(), server.args(), server.method());
|
||||
WEBUI_SECURE
|
||||
if (server.args()) {
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
WEBUI_TRACE_LOG(F("handleTK Arg: %d, %s=%s" CR), i, server.argName(i).c_str(), server.arg(i).c_str());
|
||||
@@ -957,6 +999,7 @@ void handleTK() {
|
||||
*/
|
||||
void handleIN() {
|
||||
WEBUI_TRACE_LOG(F("handleCN: uri: %s, args: %d, method: %d" CR), server.uri(), server.args(), server.method());
|
||||
WEBUI_SECURE
|
||||
if (server.args()) {
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
WEBUI_TRACE_LOG(F("handleIN Arg: %d, %s=%s" CR), i, server.argName(i).c_str(), server.arg(i).c_str());
|
||||
@@ -1026,6 +1069,7 @@ void handleIN() {
|
||||
*/
|
||||
void handleUP() {
|
||||
WEBUI_TRACE_LOG(F("handleUP: uri: %s, args: %d, method: %d" CR), server.uri(), server.args(), server.method());
|
||||
WEBUI_SECURE
|
||||
if (server.args()) {
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
WEBUI_TRACE_LOG(F("handleUP Arg: %d, %s=%s" CR), i, server.argName(i).c_str(), server.arg(i).c_str());
|
||||
@@ -1110,6 +1154,7 @@ void sendRestartPage() {
|
||||
*/
|
||||
void handleCS() {
|
||||
WEBUI_TRACE_LOG(F("handleCS: uri: %s, args: %d, method: %d" CR), server.uri(), server.args(), server.method());
|
||||
WEBUI_SECURE
|
||||
if (server.args() && server.hasArg("c2")) {
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
WEBUI_TRACE_LOG(F("handleCS Arg: %d, %s=%s" CR), i, server.argName(i).c_str(), server.arg(i).c_str());
|
||||
@@ -1173,6 +1218,7 @@ void handleCS() {
|
||||
*
|
||||
*/
|
||||
void notFound() {
|
||||
WEBUI_SECURE
|
||||
# ifdef WEBUI_DEVELOPMENT
|
||||
String path = server.uri();
|
||||
if (!exists(path)) {
|
||||
@@ -1196,6 +1242,7 @@ void notFound() {
|
||||
void WebUISetup() {
|
||||
WEBUI_TRACE_LOG(F("ZwebUI setup start" CR));
|
||||
|
||||
WebUIConfig_load();
|
||||
webUIQueue = xQueueCreate(5, sizeof(webUIQueueMessage*));
|
||||
|
||||
# ifdef WEBUI_DEVELOPMENT
|
||||
@@ -1222,6 +1269,7 @@ void WebUISetup() {
|
||||
server.on("/cn", handleCN); // Configuration
|
||||
server.on("/wi", handleWI); // Configure Wifi
|
||||
server.on("/mq", handleMQ); // Configure MQTT
|
||||
server.on("/wu", handleWU); // Configure WebUI
|
||||
# if defined(ZgatewayCloud)
|
||||
server.on("/cl", handleCL); // Configure Cloud
|
||||
server.on("/tk", handleTK); // Store Device Token
|
||||
@@ -1233,6 +1281,8 @@ void WebUISetup() {
|
||||
|
||||
Log.begin(LOG_LEVEL, &WebLog);
|
||||
|
||||
Log.trace(F("[WebUI] displayMetric %T" CR), displayMetric);
|
||||
Log.trace(F("[WebUI] WebUI Secure %T" CR), webUISecure);
|
||||
Log.notice(F("OpenMQTTGateway URL: http://%s/" CR), WiFi.localIP().toString().c_str());
|
||||
displayPrint("URL: http://", (char*)WiFi.localIP().toString().c_str());
|
||||
Log.notice(F("ZwebUI setup done" CR));
|
||||
@@ -1306,6 +1356,7 @@ String stateWebUIStatus() {
|
||||
StaticJsonDocument<JSON_MSG_BUFFER> jsonBuffer;
|
||||
JsonObject WebUIdata = jsonBuffer.to<JsonObject>();
|
||||
WebUIdata["displayMetric"] = (bool)displayMetric;
|
||||
WebUIdata["webUISecure"] = (bool)webUISecure;
|
||||
WebUIdata["displayQueue"] = uxQueueMessagesWaiting(webUIQueue);
|
||||
;
|
||||
|
||||
@@ -1321,25 +1372,27 @@ bool WebUIConfig_save() {
|
||||
StaticJsonDocument<JSON_MSG_BUFFER> jsonBuffer;
|
||||
JsonObject jo = jsonBuffer.to<JsonObject>();
|
||||
jo["displayMetric"] = (bool)displayMetric;
|
||||
jo["webUISecure"] = (bool)webUISecure;
|
||||
// Save config into NVS (non-volatile storage)
|
||||
String conf = "";
|
||||
serializeJson(jsonBuffer, conf);
|
||||
preferences.begin(Gateway_Short_Name, false);
|
||||
preferences.putString("WebUIConfig", conf);
|
||||
int result = preferences.putString("WebUIConfig", conf);
|
||||
preferences.end();
|
||||
Log.trace(F("[WebUI] WebUIConfig_save: %s, result: %d" CR), conf.c_str(), result);
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebUIConfig_init() {
|
||||
boolean displayMetric = DISPLAY_METRIC;
|
||||
displayMetric = DISPLAY_METRIC;
|
||||
webUISecure = WEBUI_AUTH;
|
||||
Log.notice(F("WebUI config initialised" CR));
|
||||
}
|
||||
|
||||
bool WebUIConfig_load() {
|
||||
StaticJsonDocument<JSON_MSG_BUFFER> jsonBuffer;
|
||||
preferences.begin(Gateway_Short_Name, true);
|
||||
String exists = preferences.getString("WebUIConfig", "{}");
|
||||
if (exists != "{}") {
|
||||
if (preferences.isKey("WebUIConfig")) {
|
||||
auto error = deserializeJson(jsonBuffer, preferences.getString("WebUIConfig", "{}"));
|
||||
preferences.end();
|
||||
if (error) {
|
||||
@@ -1352,6 +1405,7 @@ bool WebUIConfig_load() {
|
||||
}
|
||||
JsonObject jo = jsonBuffer.as<JsonObject>();
|
||||
displayMetric = jo["displayMetric"].as<bool>();
|
||||
webUISecure = jo["webUISecure"].as<bool>();
|
||||
return true;
|
||||
} else {
|
||||
preferences.end();
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
#else
|
||||
# define configure_3
|
||||
#endif
|
||||
#define configure_4 "<p><form action='lo' method='get'><button>Configure Logging</button></form></p>"
|
||||
#define configure_5
|
||||
#define configure_4 "<p><form action='wu' method='get'><button>Configure WebUI</button></form></p>"
|
||||
#define configure_5 "<p><form action='lo' method='get'><button>Configure Logging</button></form></p>"
|
||||
#define configure_6
|
||||
#define configure_7
|
||||
#define configure_8
|
||||
@@ -83,8 +83,6 @@ const char console_body[] = body_header "<br><textarea readonly id='t1' cols='34
|
||||
|
||||
const char information_body[] = body_header "<style>td {padding: 0px 5px;}</style><div id='i' name='i'></div>" body_footer_main_menu;
|
||||
|
||||
// <fieldset class=\"set1\"><legend><span><b> Upgrade by file upload </b></span></legend><form method='post' action='up' enctype='multipart/form-data'><br><input type='file' name='u2'><br><br><button type='submit' onclick='eb(\"f1\").style.display=\"none\";eb(\"f2\").style.display=\"block\";this.form.submit();'>Start upgrade</button></form></fieldset>
|
||||
|
||||
const char upgrade_body[] = body_header "<div id='f1' style='display:block;'><fieldset class=\"set1\"><legend><span><b>Upgrade by Web Server</b></span></legend><form method='get' action='up'><br><b>OTA URL</b><br><input id='o' placeholder=\"OTA_URL\" value=\"%s\"><br><br><button type='submit' class='button bgrn'>Start upgrade</button></form></fieldset><br><br><fieldset class=\"set1\"><legend><span><b>Upgrade to Level</b></span></legend><form method='get' action='up'><p><b>Level</b><br><select id='le'><option value='1'>Latest Release</option><option value='2'>Development</option></select></p><br><button type='submit' class='button bgrn'>Start upgrade</button></form></fieldset></div><div id='f2' style='display:none;text-align:center;'><b>Upload started ...</b></div><div id=but2d style=\"display: block;\"></div><p>" body_footer_main_menu;
|
||||
|
||||
const char config_wifi_body[] = body_header "%s<br><div><a href='/wi?scan='><b>Scan for all WiFi Networks</b></a></div><br><fieldset class=\"set1\"><legend><span><b>WiFi Parameters</b></span></legend><form method='get' action='wi'><p><b>WiFi Network</b> () <br><input id='s1' placeholder=\"Type or Select your WiFi Network\" value=\"%s\"></p><p><label><b>WiFi Password</b><input type='checkbox' onclick='sp(\"p1\")'></label><br><input id='p1' type='password' placeholder=\"Enter your WiFi Password\" value=\"%s\"></p><br><button name='save' type='submit' class='button bgrn'>Save</button></form></fieldset>" body_footer_config_menu;
|
||||
@@ -95,6 +93,8 @@ const char config_mqtt_body[] = body_header "<fieldset class=\"set1\"><legend><s
|
||||
|
||||
const char config_logging_body[] = body_header "<fieldset class=\"set1\"><legend><span><b>OpenMQTTGateway Logging</b></span></legend><form method='get' action='lo'><p><b>Log Level</b><br><select id='lo'><option %s value='0'>Silent</option><option %s value='1'>Fatal</option><option %s value='2'>Error</option><option %s value='3'>Warning</option><option %s value='4'>Notice</option><option %s value='5'>Trace</option><option %s value='6'>Verbose</option></select></p><br><button name='save' type='submit' class='button bgrn'>Save</button></form></fieldset>" body_footer_config_menu;
|
||||
|
||||
const char config_webui_body[] = body_header "<fieldset class=\"set1\"><legend><span><b>Configure WebUI</b></span></legend><form method='get' action='wu'><p><b>Display Metric</b><br><input id='dm' type='checkbox' %s></p><p><b>Secure WebUI</b><br><input id='sw' type='checkbox' %s></p><br><button name='save' type='submit' class='button bgrn'>Save</button></form></fieldset>" body_footer_config_menu;
|
||||
|
||||
const char footer[] = "<div style='text-align:right;font-size:11px;'><hr/><a href='https://community.openmqttgateway.com' target='_blank' style='color:#aaa;'>%s</a></div></div></body></html>";
|
||||
|
||||
#endif
|
||||
@@ -57,8 +57,23 @@
|
||||
# define WEBUI_TRACE_LOG(...)
|
||||
#endif
|
||||
|
||||
#ifndef WEBUI_AUTH
|
||||
# define WEBUI_AUTH true // Default to WebUI authentication
|
||||
#endif
|
||||
|
||||
#ifndef WEBUI_LOGIN
|
||||
# define WEBUI_LOGIN "admin"
|
||||
#endif
|
||||
|
||||
/*------------------- End of Compiler Directives ----------------------*/
|
||||
|
||||
#define WEBUI_SECURE \
|
||||
if (webUISecure) { \
|
||||
if (!server.authenticate(www_username, ota_pass)) { \
|
||||
return server.requestAuthentication(DIGEST_AUTH, gateway_name, authFailResponse); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MAX_WIFI_NETWORKS_TO_SHOW 10
|
||||
|
||||
/*
|
||||
|
||||
Reference in new issue
Block a user