Poslání requestu pře HTTPs

Odpovědět
martinkouda
Příspěvky: 20
Registrován: 27 kvě 2020, 17:01
Reputation: 0

Poslání requestu pře HTTPs

Příspěvek od martinkouda » 04 čer 2020, 19:56

Ahoj,
nemáte někdo zkušenosti s posíláním GET/POST požadavku přes HTTPs z ESP8266? Vyzkoušel jsem spousty tutoriálů/příkladů, které se jen dají na internetu najít, ale každý požadavek skončil při pokusu o kontaktování serveru chybou -1 (refused). K WiFi jsem se samozřejmě připojil. Nepoužíváte někdo tento přístup? Můžu si samozřejmě API vypublikovat jako HTTP, ale radši bych přes HTTPs. Uvítal bych nějaký funkční příklad.
Díky,
Martin

martinius96
Příspěvky: 579
Registrován: 01 srp 2017, 19:29
Reputation: 0
Bydliště: Poprad
Kontaktovat uživatele:

Re: Poslání requestu pře HTTPs

Příspěvek od martinius96 » 04 čer 2020, 20:10

Ahoj, používam to bežne.. Využívam Arduino Core 2.5.2 pre ESP8266, malo by to byť kompatibilné aj pre vyššie verzie.
Potrebuješ získať HTTPS fingerprint v SHA1 formáte danej webovej lokality, ktorú vložíš do programu a používaš ho pri nadviazaní spojenia.
Ako je z programu nižšie zrejmé, používam tam fingerprint 00 2c c1 3a 3c fd a2 0a a3 f1 19 1a ee ee 54 72 93 56 7d 1b, ktorý som získal zo svojho webu v prehliadači.
Obrázek
Tá implementácia je pre WiFiClientSecure.h (Secured socket). Ak používaš HTTPClient, alebo BearSSL s HTTPS, tam môže byť implementácia iná. Radšej mám však ESP32, ktoré využíva Root CA certifikát, lebo ten je platný 10 rokov. Tento fingerprint platí tak dlho ako certifikát stránky, keď sa predĺži, zmení sa i fingerprint. Takže obnovuješ ho vždy raz za 2 roky (to je maximálna doba platností certifikátov pre weby dnes).
Program pre ESP8266 z RFID vrátnika s HTTPS:

Kód: Vybrat vše

/*|----------------------------------------------------------|*/
/*|SKETCH PRE RFID SYSTEM S WEB ADMINISTRACIOU  (FUNGUJE)    |*/
/*|VYHOTOVIL: MARTIN CHLEBOVEC                               |*/
/*|FB: https://www.facebook.com/martin.s.chlebovec           |*/
/*|EMAIL: martinius96@gmail.com                              |*/
/*|Doska: NodeMCU v3 Lolin (v2 compatible)                   |*/
/*|CORE: 2.5.0 (2.5.2)                                       |*/
/*|WEB: https://arduino.php5.sk                              |*/
/*|----------------------------------------------------------|*/
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <SPI.h>
#include <RFID.h>

const char * ssid = "MenoWifiSiete";
const char * password = "HesloWifiSiete";
const char * host = "arduino.php5.sk"; //bez https a www
const int httpsPort = 443; //https port

const int rele = 16; //GPIO16 == D0
const char fingerprint[] PROGMEM = "00 2c c1 3a 3c fd a2 0a a3 f1 19 1a ee ee 54 72 93 56 7d 1b";
#define SS_PIN 4
#define RST_PIN 5
RFID rfid(SS_PIN, RST_PIN);
unsigned long kod;
void setup() {
  Serial.begin(9600);
  SPI.begin();
  rfid.init();
  pinMode(rele, OUTPUT);
  digitalWrite(rele, HIGH); //hotfix
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi uspesne pripojene");
  Serial.println("IP adresa: ");
  Serial.println(WiFi.localIP());
  Serial.println("Ready");
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) {
    WiFi.begin(ssid, password);
  }
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  if (rfid.isCard()) {
    if (rfid.readCardSerial()) {
      Serial.println(" ");
      Serial.println("Card found");
      kod = 10000 * rfid.serNum[4] + 1000 * rfid.serNum[3] + 100 * rfid.serNum[2] + 10 * rfid.serNum[1] + rfid.serNum[0];
      Serial.println(kod);
      WiFiClientSecure client;
      Serial.printf("Using fingerprint '%s'\n", fingerprint);
      client.setFingerprint(fingerprint);
      String kodik = String(kod);
      String data = "kod=" + kodik;
      String url = "/rfid/karta.php";
      if (client.connect(host, httpsPort)) {
        client.println("POST " + url + " HTTP/1.0");
        client.println("Host: " + (String)host);
        client.println("User-Agent: ESP8266");
        client.println("Connection: close");
        client.println("Content-Type: application/x-www-form-urlencoded;");
        client.print("Content-Length: ");
        client.println(data.length());
        client.println();
        client.println(data);
        while (client.connected()) {
          String line = client.readStringUntil('\n');
          if (line == "\r") {
            break;
          }
        }
        String line = client.readStringUntil('\n');
        if (line == "OK") {
          digitalWrite(rele, LOW); //invertovane spinane rele active LOW
          delay(5500);              //cas otvorenia dveri
          digitalWrite(rele, HIGH); //zatvor zamok
        } else if (line == "NO") {
          digitalWrite(rele, HIGH);
        } else {
          Serial.println("Prosim pockajte s dalsim overenim karty 5 sekund!");
        }
      }
      client.stop();
    }
  }
  rfid.halt();
}

KamilV
Příspěvky: 479
Registrován: 03 dub 2018, 15:27
Reputation: 0
Bydliště: Olomouc

Re: Poslání requestu pře HTTPs

Příspěvek od KamilV » 05 čer 2020, 08:08

martinius96 píše:
04 čer 2020, 20:10
Tento fingerprint platí tak dlho ako certifikát stránky, keď sa predĺži, zmení sa i fingerprint. Takže obnovuješ ho vždy raz za 2 roky (to je maximálna doba platností certifikátov pre weby dnes).
Třeba certifikáty LetsCrypt se obnovují co 3 měsíce... To člověk musí co 3 měsíce měnit firmware? A proč vlastně musí být otisk natvrdo v kódu? Prohlížeče také neznají otisky všech webů a spojení naváží...

martinkouda
Příspěvky: 20
Registrován: 27 kvě 2020, 17:01
Reputation: 0

Re: Poslání requestu pře HTTPs

Příspěvek od martinkouda » 05 čer 2020, 11:06

martinius96 píše:
04 čer 2020, 20:10
Ahoj, používam to bežne.. Využívam Arduino Core 2.5.2 pre ESP8266, malo by to byť kompatibilné aj pre vyššie verzie.
Potrebuješ získať HTTPS fingerprint v SHA1 formáte danej webovej lokality, ktorú vložíš do programu a používaš ho pri nadviazaní spojenia.
Ako je z programu nižšie zrejmé, používam tam fingerprint 00 2c c1 3a 3c fd a2 0a a3 f1 19 1a ee ee 54 72 93 56 7d 1b, ktorý som získal zo svojho webu v prehliadači.
Obrázek
Tá implementácia je pre WiFiClientSecure.h (Secured socket). Ak používaš HTTPClient, alebo BearSSL s HTTPS, tam môže byť implementácia iná. Radšej mám však ESP32, ktoré využíva Root CA certifikát, lebo ten je platný 10 rokov. Tento fingerprint platí tak dlho ako certifikát stránky, keď sa predĺži, zmení sa i fingerprint. Takže obnovuješ ho vždy raz za 2 roky (to je maximálna doba platností certifikátov pre weby dnes).
Program pre ESP8266 z RFID vrátnika s HTTPS:

Kód: Vybrat vše

/*|----------------------------------------------------------|*/
/*|SKETCH PRE RFID SYSTEM S WEB ADMINISTRACIOU  (FUNGUJE)    |*/
/*|VYHOTOVIL: MARTIN CHLEBOVEC                               |*/
/*|FB: https://www.facebook.com/martin.s.chlebovec           |*/
/*|EMAIL: martinius96@gmail.com                              |*/
/*|Doska: NodeMCU v3 Lolin (v2 compatible)                   |*/
/*|CORE: 2.5.0 (2.5.2)                                       |*/
/*|WEB: https://arduino.php5.sk                              |*/
/*|----------------------------------------------------------|*/
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <SPI.h>
#include <RFID.h>

const char * ssid = "MenoWifiSiete";
const char * password = "HesloWifiSiete";
const char * host = "arduino.php5.sk"; //bez https a www
const int httpsPort = 443; //https port

const int rele = 16; //GPIO16 == D0
const char fingerprint[] PROGMEM = "00 2c c1 3a 3c fd a2 0a a3 f1 19 1a ee ee 54 72 93 56 7d 1b";
#define SS_PIN 4
#define RST_PIN 5
RFID rfid(SS_PIN, RST_PIN);
unsigned long kod;
void setup() {
  Serial.begin(9600);
  SPI.begin();
  rfid.init();
  pinMode(rele, OUTPUT);
  digitalWrite(rele, HIGH); //hotfix
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi uspesne pripojene");
  Serial.println("IP adresa: ");
  Serial.println(WiFi.localIP());
  Serial.println("Ready");
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) {
    WiFi.begin(ssid, password);
  }
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  if (rfid.isCard()) {
    if (rfid.readCardSerial()) {
      Serial.println(" ");
      Serial.println("Card found");
      kod = 10000 * rfid.serNum[4] + 1000 * rfid.serNum[3] + 100 * rfid.serNum[2] + 10 * rfid.serNum[1] + rfid.serNum[0];
      Serial.println(kod);
      WiFiClientSecure client;
      Serial.printf("Using fingerprint '%s'\n", fingerprint);
      client.setFingerprint(fingerprint);
      String kodik = String(kod);
      String data = "kod=" + kodik;
      String url = "/rfid/karta.php";
      if (client.connect(host, httpsPort)) {
        client.println("POST " + url + " HTTP/1.0");
        client.println("Host: " + (String)host);
        client.println("User-Agent: ESP8266");
        client.println("Connection: close");
        client.println("Content-Type: application/x-www-form-urlencoded;");
        client.print("Content-Length: ");
        client.println(data.length());
        client.println();
        client.println(data);
        while (client.connected()) {
          String line = client.readStringUntil('\n');
          if (line == "\r") {
            break;
          }
        }
        String line = client.readStringUntil('\n');
        if (line == "OK") {
          digitalWrite(rele, LOW); //invertovane spinane rele active LOW
          delay(5500);              //cas otvorenia dveri
          digitalWrite(rele, HIGH); //zatvor zamok
        } else if (line == "NO") {
          digitalWrite(rele, HIGH);
        } else {
          Serial.println("Prosim pockajte s dalsim overenim karty 5 sekund!");
        }
      }
      client.stop();
    }
  }
  rfid.halt();
}
Super, díky moc za popostrčení. U mě byl asi ve finále problém v tom otisku. Ve všech příkladech byl vypršený. Tak jsem si ho zjistil znova a už to funguje.
Martin

martinius96
Příspěvky: 579
Registrován: 01 srp 2017, 19:29
Reputation: 0
Bydliště: Poprad
Kontaktovat uživatele:

Re: Poslání requestu pře HTTPs

Příspěvek od martinius96 » 05 čer 2020, 12:24

KamilV píše:
05 čer 2020, 08:08
martinius96 píše:
04 čer 2020, 20:10
Tento fingerprint platí tak dlho ako certifikát stránky, keď sa predĺži, zmení sa i fingerprint. Takže obnovuješ ho vždy raz za 2 roky (to je maximálna doba platností certifikátov pre weby dnes).
Třeba certifikáty LetsCrypt se obnovují co 3 měsíce... To člověk musí co 3 měsíce měnit firmware? A proč vlastně musí být otisk natvrdo v kódu? Prohlížeče také neznají otisky všech webů a spojení naváží...
Prehliadač používa (Root) CA certifikáty per HTTPS spoojenie. Teda ak máš Let's encrypt certifikát na webserveri, vždy ho vydáva certifikačná autorita DST Root CA X3. Jej certifikát máš uložený v tvojom počítači, respektíve v prehliadači a ten využívaš pri otváraní HTTPS webovej stránky s Let's encrypt certifikátom. Ak budeš používať ESP8266 ktoré využíva fingerprint, tak ho musíš každé 3 mesiace obnoviť. ESP32 to používa tak ako browser, že využíva certifikát certifikačnej autority v programe (formát certifikátu .pem).

Teda v prehliadači a v ESP32 to môžeš využívať až 10 rokov (certifikačná autorita sa nemení, menil by si to iba v prípade, že prejdeš z Let's Encrypt na Rapid SSL, Digicert alebo iné CA). Prehliadač pri aktualizácii dostáva aj nové CA certifikáty, teda i keď by DST Root CA X3 pre Let's ecrypt končil, sám prehliadač dostane v aktualizácii jeho novú verziu, čiže to ani nepostrehneš, že došlo k nejakej zmene.

Častokrát sa práve kvôli tomu fingeprintu dáva do programov pre ESP8266 aj možnosť ALLOW INSECURE connection, aby to fungovalo aj po vypršaní platnosti certifikátu s daným fingerprintom.

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 10 hostů