Skip to content

Commit b51c58b

Browse files
authored
Merge pull request #28 from sq5gvm/master
Add password protection to web interface
2 parents 1ed404a + 8451f8f commit b51c58b

File tree

3 files changed

+96
-13
lines changed

3 files changed

+96
-13
lines changed

include/config.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
int8_t _modbusRtsPin;
1717
unsigned long _serialBaudRate;
1818
uint32_t _serialConfig;
19+
String _webPassword;
1920
public:
2021
Config();
2122
void begin(Preferences *prefs);
@@ -43,6 +44,8 @@
4344
void setSerialParity(uint8_t value);
4445
uint8_t getSerialStopBits();
4546
void setSerialStopBits(uint8_t value);
47+
String getWebPassword();
48+
void setWebPassword(String value);
4649
};
4750
#ifdef DEBUG
4851
#define dbg(x...) debugSerial.print(x);

src/config.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Config::Config()
99
,_modbusRtsPin(-1)
1010
,_serialBaudRate(115200)
1111
,_serialConfig(SERIAL_8N1)
12+
,_webPassword("")
1213
{}
1314

1415
void Config::begin(Preferences *prefs)
@@ -21,6 +22,7 @@ void Config::begin(Preferences *prefs)
2122
_modbusRtsPin = _prefs->getChar("modbusRtsPin", _modbusRtsPin);
2223
_serialBaudRate = _prefs->getULong("serialBaudRate", _serialBaudRate);
2324
_serialConfig = _prefs->getULong("serialConfig", _serialConfig);
25+
_webPassword = _prefs->getString("webPassword", _webPassword);
2426
}
2527

2628
uint16_t Config::getTcpPort(){
@@ -153,4 +155,16 @@ void Config::setSerialStopBits(uint8_t value){
153155
if (stopbits == value) return;
154156
_serialConfig = (_serialConfig & 0xffffffcf) | value;
155157
_prefs->putULong("serialConfig", _serialConfig);
156-
}
158+
}
159+
160+
161+
String Config::getWebPassword(){
162+
return _webPassword;
163+
}
164+
165+
void Config::setWebPassword(String value){
166+
auto webpass = getWebPassword();
167+
if (webpass == value) return;
168+
_webPassword = value;
169+
_prefs->putString("webPassword", _webPassword);
170+
}

src/pages.cpp

Lines changed: 78 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
#include "pages.h"
22
#define ETAG "\"" __DATE__ "" __TIME__ "\""
3+
#define ADMIN_WEB_PASS \
4+
if ((!config->getWebPassword().equals("")) && (!request->authenticate("admin", config->getWebPassword().c_str()))) \
5+
return request->requestAuthentication();
6+
#define WEB_PASS_PLACEHOLDER "****"
7+
38

49
void setupPages(AsyncWebServer *server, ModbusClientRTU *rtu, ModbusBridgeWiFi *bridge, Config *config, WiFiManager *wm){
5-
server->on("/", HTTP_GET, [](AsyncWebServerRequest *request){
10+
server->on("/", HTTP_GET, [config](AsyncWebServerRequest *request){
11+
12+
ADMIN_WEB_PASS;
13+
614
dbgln("[webserver] GET /");
715
auto *response = request->beginResponseStream("text/html");
816
sendResponseHeader(response, "Main");
@@ -15,7 +23,10 @@ void setupPages(AsyncWebServer *server, ModbusClientRTU *rtu, ModbusBridgeWiFi *
1523
sendResponseTrailer(response);
1624
request->send(response);
1725
});
18-
server->on("/status", HTTP_GET, [rtu, bridge](AsyncWebServerRequest *request){
26+
server->on("/status", HTTP_GET, [rtu, bridge, config](AsyncWebServerRequest *request){
27+
28+
ADMIN_WEB_PASS;
29+
1930
dbgln("[webserver] GET /status");
2031
auto *response = request->beginResponseStream("text/html");
2132
sendResponseHeader(response, "Status");
@@ -42,7 +53,10 @@ void setupPages(AsyncWebServer *server, ModbusClientRTU *rtu, ModbusBridgeWiFi *
4253
sendResponseTrailer(response);
4354
request->send(response);
4455
});
45-
server->on("/reboot", HTTP_GET, [](AsyncWebServerRequest *request){
56+
server->on("/reboot", HTTP_GET, [config](AsyncWebServerRequest *request){
57+
58+
ADMIN_WEB_PASS;
59+
4660
dbgln("[webserver] GET /reboot");
4761
auto *response = request->beginResponseStream("text/html");
4862
sendResponseHeader(response, "Really?");
@@ -53,14 +67,20 @@ void setupPages(AsyncWebServer *server, ModbusClientRTU *rtu, ModbusBridgeWiFi *
5367
sendResponseTrailer(response);
5468
request->send(response);
5569
});
56-
server->on("/reboot", HTTP_POST, [](AsyncWebServerRequest *request){
70+
server->on("/reboot", HTTP_POST, [config](AsyncWebServerRequest *request){
71+
72+
ADMIN_WEB_PASS;
73+
5774
dbgln("[webserver] POST /reboot");
5875
request->redirect("/");
5976
dbgln("[webserver] rebooting...")
6077
ESP.restart();
6178
dbgln("[webserver] rebooted...")
6279
});
6380
server->on("/config", HTTP_GET, [config](AsyncWebServerRequest *request){
81+
82+
ADMIN_WEB_PASS;
83+
6484
dbgln("[webserver] GET /config");
6585
auto *response = request->beginResponseStream("text/html");
6686
sendResponseHeader(response, "Modbus TCP");
@@ -192,6 +212,19 @@ void setupPages(AsyncWebServer *server, ModbusClientRTU *rtu, ModbusBridgeWiFi *
192212
"</td>"
193213
"</tr>"
194214
"</table>");
215+
216+
response->print( "<h3>Other</h3>"
217+
"<table>"
218+
"<tr>"
219+
"<td>"
220+
"<label for=\"wp\">Web password</label>"
221+
"</td>"
222+
"<td>");
223+
response->printf("<input type=\"password\" min=\"0\" id=\"wp\" name=\"wp\" value=\"%s\">", WEB_PASS_PLACEHOLDER); // we're not returning configured password to user instead we're sending placeholder
224+
response->print("</td>"
225+
"</tr>"
226+
"</table>");
227+
195228
response->print("<button class=\"r\">Save</button>"
196229
"</form>"
197230
"<p></p>");
@@ -207,6 +240,9 @@ void setupPages(AsyncWebServer *server, ModbusClientRTU *rtu, ModbusBridgeWiFi *
207240
request->send(response);
208241
});
209242
server->on("/config", HTTP_POST, [config](AsyncWebServerRequest *request){
243+
244+
ADMIN_WEB_PASS;
245+
210246
dbgln("[webserver] POST /config");
211247
if (request->hasParam("tp", true)){
212248
auto port = request->getParam("tp", true)->value().toInt();
@@ -263,9 +299,21 @@ void setupPages(AsyncWebServer *server, ModbusClientRTU *rtu, ModbusBridgeWiFi *
263299
config->setSerialStopBits(stop);
264300
dbgln("[webserver] saved serial stop bits");
265301
}
302+
if (request->hasParam("wp", true)){
303+
String wp = request->getParam("wp", true)->value();
304+
if (!wp.equals(WEB_PASS_PLACEHOLDER)) { // if we get default value prefilled in the wp input we're not changing current one
305+
config->setWebPassword(wp);
306+
dbgln("[webserver] saved web password");
307+
} else {
308+
dbgln("[webserver] web password not changed");
309+
}
310+
}
266311
request->redirect("/");
267312
});
268-
server->on("/debug", HTTP_GET, [](AsyncWebServerRequest *request){
313+
server->on("/debug", HTTP_GET, [config](AsyncWebServerRequest *request){
314+
315+
ADMIN_WEB_PASS;
316+
269317
dbgln("[webserver] GET /debug");
270318
auto *response = request->beginResponseStream("text/html");
271319
sendResponseHeader(response, "Debug");
@@ -274,7 +322,10 @@ void setupPages(AsyncWebServer *server, ModbusClientRTU *rtu, ModbusBridgeWiFi *
274322
sendResponseTrailer(response);
275323
request->send(response);
276324
});
277-
server->on("/debug", HTTP_POST, [rtu](AsyncWebServerRequest *request){
325+
server->on("/debug", HTTP_POST, [rtu, config](AsyncWebServerRequest *request){
326+
327+
ADMIN_WEB_PASS;
328+
278329
dbgln("[webserver] POST /debug");
279330
String slaveId = "1";
280331
if (request->hasParam("slave", true)){
@@ -322,7 +373,10 @@ void setupPages(AsyncWebServer *server, ModbusClientRTU *rtu, ModbusBridgeWiFi *
322373
sendResponseTrailer(response);
323374
request->send(response);
324375
});
325-
server->on("/update", HTTP_GET, [](AsyncWebServerRequest *request){
376+
server->on("/update", HTTP_GET, [config](AsyncWebServerRequest *request){
377+
378+
ADMIN_WEB_PASS;
379+
326380
dbgln("[webserver] GET /update");
327381
auto *response = request->beginResponseStream("text/html");
328382
sendResponseHeader(response, "Firmware Update");
@@ -336,7 +390,10 @@ void setupPages(AsyncWebServer *server, ModbusClientRTU *rtu, ModbusBridgeWiFi *
336390
sendResponseTrailer(response);
337391
request->send(response);
338392
});
339-
server->on("/update", HTTP_POST, [](AsyncWebServerRequest *request){
393+
server->on("/update", HTTP_POST, [config](AsyncWebServerRequest *request){
394+
395+
ADMIN_WEB_PASS;
396+
340397
request->onDisconnect([](){
341398
ESP.restart();
342399
});
@@ -356,6 +413,9 @@ void setupPages(AsyncWebServer *server, ModbusClientRTU *rtu, ModbusBridgeWiFi *
356413
request->send(response);
357414
}
358415
}, [&](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
416+
417+
ADMIN_WEB_PASS;
418+
359419
dbg("[webserver] OTA progress ");dbgln(index);
360420
if (!index) {
361421
//TODO add MD5 Checksum and Update.setMD5
@@ -380,7 +440,10 @@ void setupPages(AsyncWebServer *server, ModbusClientRTU *rtu, ModbusBridgeWiFi *
380440
return;
381441
}
382442
});
383-
server->on("/wifi", HTTP_GET, [](AsyncWebServerRequest *request){
443+
server->on("/wifi", HTTP_GET, [config](AsyncWebServerRequest *request){
444+
445+
ADMIN_WEB_PASS;
446+
384447
dbgln("[webserver] GET /wifi");
385448
auto *response = request->beginResponseStream("text/html");
386449
sendResponseHeader(response, "WiFi reset");
@@ -396,7 +459,10 @@ void setupPages(AsyncWebServer *server, ModbusClientRTU *rtu, ModbusBridgeWiFi *
396459
sendResponseTrailer(response);
397460
request->send(response);
398461
});
399-
server->on("/wifi", HTTP_POST, [wm](AsyncWebServerRequest *request){
462+
server->on("/wifi", HTTP_POST, [wm, config](AsyncWebServerRequest *request){
463+
464+
ADMIN_WEB_PASS;
465+
400466
dbgln("[webserver] POST /wifi");
401467
request->redirect("/");
402468
wm->erase();
@@ -409,7 +475,7 @@ void setupPages(AsyncWebServer *server, ModbusClientRTU *rtu, ModbusBridgeWiFi *
409475
dbgln("[webserver] GET /favicon.ico");
410476
request->send(204);//TODO add favicon
411477
});
412-
server->on("/style.css", [](AsyncWebServerRequest *request){
478+
server->on("/style.css", [config](AsyncWebServerRequest *request){
413479
if (request->hasHeader("If-None-Match")){
414480
auto header = request->getHeader("If-None-Match");
415481
if (header->value() == String(ETAG)){
@@ -444,7 +510,7 @@ void setupPages(AsyncWebServer *server, ModbusClientRTU *rtu, ModbusBridgeWiFi *
444510
response->addHeader("ETag", ETAG);
445511
request->send(response);
446512
});
447-
server->onNotFound([](AsyncWebServerRequest *request){
513+
server->onNotFound([config](AsyncWebServerRequest *request){
448514
dbg("[webserver] request to ");dbg(request->url());dbgln(" not found");
449515
request->send(404, "text/plain", "404");
450516
});

0 commit comments

Comments
 (0)