无法使用WifiClientSecure连接ESP8266的https协议

5

我正在尝试通过unwiredlabs获取ESP8266的位置。我按照这个介绍进行操作。 以下是我的arduino代码:

#include <ESP8266HTTPClient.h>
#include  <ArduinoJson.h>
#include "ESP8266WiFi.h"

char myssid[] = "Your wifi/hotspot name";
char mypass[] = "Your password";

const char* Host = "www.unwiredlabs.com";
String endpoint = "/v2/process.php";

String token = "d99cccda52ec0b";

String jsonString = "{\n";

double latitude = 0.0;
double longitude = 0.0;
double accuracy = 0.0;

void setup(){
    Serial.begin(115200);

    // Set WiFi to station mode and disconnect from an AP if it was previously connected
    WiFi.mode(WIFI_STA);
    WiFi.disconnect();
    Serial.println("Setup done");

    // We start by connecting to a WiFi network
    Serial.print("Connecting to ");
    Serial.println(myssid);
    WiFi.begin(myssid, mypass);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println(".");
}

void loop() {
    char bssid[6];
    DynamicJsonBuffer jsonBuffer;

    // WiFi.scanNetworks will return the number of networks found
    int n = WiFi.scanNetworks();
    Serial.println("scan done");

    if (n == 0 ) {
        Serial.println("No networks available");
    } else {
        Serial.print(n);
        Serial.println(" networks found");
    }

      // now build the jsonString...
      jsonString = "{\n";
      jsonString += "\"token\" : \"";
      jsonString += token;
      jsonString += "\",\n";
      jsonString += "\"id\" : \"saikirandevice01\",\n";
      jsonString += "\"wifi\": [\n";
      for (int j = 0; j < n; ++j) {
          jsonString += "{\n";
          jsonString += "\"bssid\" : \"";
          jsonString += (WiFi.BSSIDstr(j));
          jsonString += "\",\n";
          jsonString += "\"signal\": ";
          jsonString += WiFi.RSSI(j);
          jsonString += "\n";
          if (j < n - 1) {
              jsonString += "},\n";
          } else {
              jsonString += "}\n";
          }
      }
      jsonString += ("]\n");
      jsonString += ("}\n");
      Serial.println(jsonString);

      WiFiClientSecure client;

      //Connect to the client and make the api call
      Serial.println("Requesting URL: https://" + (String)Host + endpoint);
      if (client.connect(Host, 443)) {
          Serial.println("Connected");
          client.println("POST " + endpoint + " HTTP/1.1");
          client.println("Host: " + (String)Host);
          client.println("Connection: close");
          client.println("Content-Type: application/json");
          client.println("User-Agent: Arduino/1.0");
          client.print("Content-Length: ");
          client.println(jsonString.length());
          client.println();
          client.print(jsonString);
          delay(500);
      }

      //Read and parse all the lines of the reply from server
      while (client.available()) {
          String line = client.readStringUntil('\r');
          JsonObject& root = jsonBuffer.parseObject(line);
          if (root.success()) {
              latitude    = root["lat"];
              longitude   = root["lon"];
              accuracy    = root["accuracy"];

              Serial.println();
              Serial.print("Latitude = ");
              Serial.println(latitude, 6);
              Serial.print("Longitude = ");
              Serial.println(longitude, 6);
              Serial.print("Accuracy = ");
              Serial.println(accuracy);
          }
      }

      Serial.println("closing connection");
      Serial.println();
      client.stop();

      delay(5000);
}

当代码被烧录到esp8266后,显示无法连接到https://www.instructables.com/v2/process.php
ESP串口输出:
... // some initial setup string
Requesting URL: https://unwiredlabs.com/v2/process.php
// if connected, "connected" was printed here, but not
closing connection

然后,我尝试在Chrome浏览器上使用URL https://unwiredlabs.com/v2/process.php。这是消息:

{
status: "error",
message: "Invalid request",
balance: 0,
help: "Check for misplaced commas and use double quotes to encapsulate strings"
}

这证明了该URL存在,但是当我在Postman上尝试时,它显示如下:Postman response 然后,我关闭了Postman上的SSL证书验证。这导致返回了一个403 Forbidden错误。因此,我认为问题的原因是WifiClientSecure的SSL证书验证。有人可以帮忙吗?

请分开打印,不要将字符串 "POST " + endpoint + " HTTP/1.1" 连接起来。 - Juraj
@Jural 感谢您的回复,但它无法解决问题,因为 client.connect() 返回了 false 值,程序没有进入 if 代码块。 - simpsons3
1个回答

1
SSL - 至少这段代码尝试使用它的方式需要连接的站点的指纹。在尝试连接该站点之前,该代码需要向其客户端对象提供该站点的指纹。
步骤1:手动从站点检索指纹: 我在Chrome中浏览https://www.unwiredlabs.com并复制了站点证书,然后在Windows上使用git bash中的openSSL提取指纹:
openssl x509 -noout -fingerprint -sha1 -inform pem -in certificate-file.cer > fingerprint.txt

我随后编辑了生成的fingerprint.txt文件,将每个“:”替换为空格。
在网上搜索如何使用Chrome或其他浏览器复制引用证书的详细信息。
步骤2:编辑代码以将指纹添加到Sketch中: 我添加了常量“sslFingerprint”,并在调用client.connect()之前添加了对client.setFingerprint()的调用。
然后,我删除了与连接到站点无关的代码,创建了一个示例Sketch,说明成功连接到unwiredlabs.com。
#include <ESP8266HTTPClient.h>
#include "ESP8266WiFi.h"

// The SSL Fingerprint of https://www.unwiredlabs.com
// Certificate expires ‎October ‎9, ‎2020
const char *sslFingerprint
  = "C3 3E 2F 21 CB 15 4E 02 D5 27 E5 F6 EF FB 31 AE 91 51 A3 5D";

char myssid[] = "yourWiFiSSID";
char mypass[] = "yourWiFiPassword";

const char* Host = "www.unwiredlabs.com";
String endpoint = "/v2/process.php";

void setup() {
  Serial.begin(9600);

  // Set WiFi to station mode and disconnect from an AP if it was previously connected
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  Serial.println("Setup done");

  // We start by connecting to a WiFi network
  Serial.print("Connecting to ");
  Serial.println(myssid);
  WiFi.begin(myssid, mypass);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(".");
}

void loop() {
  WiFiClientSecure client;

  //Connect to the client and make the api call
  Serial.println("Requesting URL: https://" + (String)Host + endpoint);
  client.setFingerprint(sslFingerprint);
  if (client.connect(Host, 443)) {
    Serial.println("Connected");
  }
  Serial.println("closing connection");
  Serial.println();
  client.stop();

  delay(5000);
}

当在Sparkfun ESP8266 Thing Dev开发板上运行时,该示例产生以下输出:
......
Requesting URL: https://www.unwiredlabs.com/v2/process.php
Connected
closing connection

附言:我使用的代码是从Github上的Arduino ESP8266支持代码HTTPSRequest示例Sketch中派生出来的:https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/HTTPSRequest/HTTPSRequest.ino - Bradford Needham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接