ESP32

ESP32 Arduino: HTTPS GET Request

기하 2021. 8. 16. 04:15

소개

이 게시물의 목적은 ESP32의 Arduino 코어를 사용하여 HTTPS를 통해 GET 요청을 수행하는 방법을 설명하는 것입니다.

HTTPS 작동 방식을 자세히 설명하는 것은 이 게시물의 범위를 벗어납니다. 따라서 기본적으로 HTTPS는 HTTP의 보안 버전입니다. 즉, 서버와 클라이언트 간에 교환되는 데이터가 암호화됩니다[1].

HTTPS 연결을 설정하기 위해 서버는 초기 프로토콜 핸드셰이크에 필요한 공개 암호화 키가 포함된 디지털 인증서를 제공해야 합니다[1].

그럼에도 불구하고 일반적으로 클라이언트는 도달하려는 서버의 인증서가 유효한지 알지 못합니다. 즉, 신뢰할 수 있는지 여부를 알 수 없습니다.

따라서 인증서 유효성 검사 절차는 연결하려는 서버의 인증서를 누가 발급했는지 확인합니다. 그런 다음 발급자의 인증서를 확인하고 여전히 신뢰할 수 없으면 다른 수준으로 올라가서 인증서 체인을 구축합니다 .

어느 시점에서 우리는 누군가를 믿어야 합니다. 일반적으로 클라이언트 는 인증 체인의 최상위 에 있는 루트 CA를 신뢰합니다 [2]. 예를 들어 브라우저에는 인증 체인에서 발견될 때 신뢰할 수 있는 CA 목록이 있습니다. 여기  에서 Mozilla의 예를 확인할 수 있습니다 .

따라서 브라우저가 아닌 ESP32에서 요청을 수행할 것이므로 도달하려는 웹 사이트의 인증 체인을 검증하기 위해 신뢰하는 인증 기관의 인증서를 지정해야 합니다. 아래에서 필요한 인증서를 얻는 방법을 살펴보겠습니다.

이 ESP32 튜토리얼의 테스트  는 ESP32 FireBeetle 보드에 통합된 DFRobot의 ESP-WROOM-32 장치를 사용하여 수행  되었습니다  .

 

루트 CA의 인증서 가져오기

테스트를 수행하기 위해 HTTPS를 통해 사용할 수 있는 가짜 온라인 REST API 웹사이트에 접속합니다. 확인할 수 있습니다 여기에 웹 브라우저, 우리가 도달하고 리턴 된 정보를 확인하고자하는 엔드 포인트를 사용하여.

루트 CA의 인증서를 얻으려면 그림 1에서 볼 수 있듯이 Firefox에서 웹 사이트에 액세스하고 URL 왼쪽에 있는 잠금 아이콘을 클릭하는 것이 쉬운 방법입니다.

API의 이 끝점은 나중에 Arduino 프로그램에서 받은 데이터와 일치해야 하는 일부 JSON 콘텐츠를 반환합니다.

그림 1 – Firefox에서 인증서 확인하기.

그런 다음 나타나는 팝업에서 그림 2에 강조 표시된 화살표를 클릭해야 합니다.

그림 2 - Firefox 인증서 팝업

그런 다음 그림 3에 강조 표시된 것처럼 "추가 정보"(내 브라우저는 포르투갈어)를 클릭해야 합니다.

그림 3 – Firefox 인증서 추가 정보.

이제 새 팝업이 열려야 합니다. 여기에서 그림 4에 강조 표시된 "인증서 보기" 버튼을 클릭합니다.

그림 4 – 인증서 팝업 보기.

다시 새 팝업이 열려야 합니다. 상단의 탭에서 "자세히"를 선택합니다. 그런 다음 그림 5와 같이 "인증서 계층 구조"라는 상자가 있는 탭으로 이동해야 합니다.

이 상자는 브라우저가 신뢰하는 루트 CA까지의 인증서 체인을 보여줍니다. 그것을 선택하고 팝업 하단에서 "내보내기" 버튼을 클릭하면 ESP32에서 사용할 인증서를 얻을 수 있습니다.

그림 5 - 인증서 체인 팝업

버튼을 클릭하면 컴퓨터의 어딘가에 저장합니다. 그런 다음 메모장++과 같은 텍스트 편집기로 엽니다. 그림 6과 유사한 결과를 얻어야 합니다.

그림 6 - 테스트 API 웹 사이트의 루트 CA 인증서.

이제 프로그램에서 사용할 수 있도록 Arduino 여러 줄 문자열로 변환해야 합니다. 간단한 복사 및 붙여넣기를 위해 최종 형식 아래에서 확인할 수 있습니다. 여기  에서 메모장++의 트릭을 확인 하여 수직 선택을 수행하여 Arduino 여러 줄 문자열에서 인증서를 전환하는 데 필요한 추가 문자를 쉽게 붙여넣을 수 있습니다.

1
2

4
5
6
7
8
9
10
11
12
13
14
15
16
17
const char* root_ca= \
"-----BEGIN CERTIFICATE-----\n" \
"MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL\n" \
"MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE\n" \
"BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT\n" \
"IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw\n" \
"MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy\n" \
"ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N\n" \
"T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv\n" \
"biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR\n" \
"FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J\n" \
"cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW\n" \
"BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/\n" \
"BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm\n" \
"fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv\n" \
"GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=\n" \
"-----END CERTIFICATE-----\n";


코드

필요한 라이브러리를 포함하여 코드를 시작합니다. ESP32를 WiFi 네트워크에 연결하는 데 필요한 WiFi.h 라이브러리 를 포함합니다 . 요청을 수행하는 데 필요한 클래스를 사용할 수 있도록 하는 HTTPClient.h 라이브러리 도 필요합니다 .

1
2
#include <WiFi.h>
#include <HTTPClient.h>

또한 연결에 필요한 WiFi 네트워크 이름(ssid)과 비밀번호를 모두 보유하기 위해 두 개의 변수를 선언해야 합니다.

1
2
const char* ssid = "yourNetworkName";
const char* password = "yourNetworkPassword";

마지막으로 이전 섹션에서 방금 가져온 CA 인증서를 여기에 붙여넣어야 합니다.

1
2

4
5
6
7
8
9
10
11
12
13
14
15
16
17
const char* root_ca= \
"-----BEGIN CERTIFICATE-----\n" \
"MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL\n" \
"MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE\n" \
"BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT\n" \
"IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw\n" \
"MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy\n" \
"ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N\n" \
"T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv\n" \
"biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR\n" \
"FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J\n" \
"cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW\n" \
"BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/\n" \
"BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm\n" \
"fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv\n" \
"GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=\n" \
"-----END CERTIFICATE-----\n";

설정 기능으로 이동하여 프로그램 결과를 출력하기 위해 직렬 연결을 엽니다. 그런 다음 이전에 선언된 자격 증명을 사용하여 ESP32를 WiFi 네트워크에 연결합니다. 당신은에서 확인할 수 있습니다  이전 게시물을 WiFi 네트워크에 연결하는 방법에 대한 자세한 설명.

이미 언급된 구성을 포함하는 설정 기능의 전체 코드는 아래에서 볼 수 있습니다.

1
2

4
5
6
7
8
9
10
11
12
13
14
void setup() {


  Serial.begin(115200);
  delay(1000);


  WiFi.begin(ssid, password);


  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }


  Serial.println("Connected to the WiFi network");
}

서버에 대한 연결을 설정하고 Arduino 메인 루프 기능에 대한 요청을 수행합니다.

요청을 수행하는 데 필요한 메소드를 노출할 HTTPClient 클래스의 객체를 선언하는 것으로 시작합니다 .

1 HTTPClient http;

그런 다음 HTTPClient 개체  begin 메서드를 호출하여 요청을 수행하려는 URL을 첫 번째 입력으로 전달하고 전역 변수로 선언한 루트 CA 인증서를 두 번째 입력으로 전달합니다.

이렇게 하면 요청 보내기를 계속하기 전에 필요한 초기화가 수행됩니다.

일반 HTTP를 사용하는 대신 HTTPS 요청을 수행하기 때문에 URL에는 HTTPS 접두사가 있어야 합니다.

1 http.begin("https://jsonplaceholder.typicode.com/posts?userId=1", root_ca); //Specify the URL and certificate

이제 실제 HTTPS GET 요청을 수행하기 위해 HTTPClient 개체 에서 GET 메서드를 호출하기만 하면 됩니다.

이 메서드 호출은 정수를 반환합니다. 값이 0보다 크면 서버에서 반환한 HTTP 코드에 해당합니다. 0보다 작으면 ESP32의 내부 오류에 해당합니다.

1 int httpCode = http.GET();

따라서 코드가 실제로 0보다 크면 HTTPClient 개체  getString 메서드를 호출하여 서버에서 반환된 응답의 페이로드를 얻을 수 있습니다 . 이름에서 알 수 있듯이 응답 페이로드가 포함된 문자열을 반환합니다.

그런 다음 페이로드와 HTTP 코드를 모두 인쇄합니다.

1
2

4
5
6
7
8
9
10
if (httpCode > 0) { //Check for the returning code


   String payload = http.getString();
   Serial.println(httpCode);
   Serial.println(payload);
}


else {
   Serial.println("Error on HTTP request");
}

마지막으로 HTTPClient 개체  end 메서드를 호출하여 리소스를 해제 합니다.

1 http.end(); //Free the resources

최종 소스 코드는 아래에서 볼 수 있습니다. 또한 요청을 진행하기 전에 WiFi 네트워크에 연결되어 있는지 확인하는 유효성 검사도 포함됩니다.

1
2

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <WiFi.h>
#include <HTTPClient.h>


const char* ssid = "yourNetworkName";
const char* password =  "yourNetworkPass";


void setup() {


  Serial.begin(115200);
  delay(1000);


  WiFi.begin(ssid, password);


  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }


  Serial.println("Connected to the WiFi network");
}


const char* root_ca= \
"-----BEGIN CERTIFICATE-----\n" \
"MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL\n" \
"MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE\n" \
"BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT\n" \
"IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw\n" \
"MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy\n" \
"ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N\n" \
"T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv\n" \
"biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR\n" \
"FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J\n" \
"cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW\n" \
"BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/\n" \
"BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm\n" \
"fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv\n" \
"GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=\n" \
"-----END CERTIFICATE-----\n";


void loop() {


  if ((WiFi.status() == WL_CONNECTED)) { //Check the current connection status


    HTTPClient http;


    http.begin("https://jsonplaceholder.typicode.com/posts?userId=1", root_ca); //Specify the URL and certificate
    int httpCode = http.GET();                                                  //Make the request


    if (httpCode > 0) { //Check for the returning code


        String payload = http.getString();
        Serial.println(httpCode);
        Serial.println(payload);
      }


    else {
      Serial.println("Error on HTTP request");
    }


    http.end(); //Free the resources
  }


  delay(10000);
}


코드 테스트

코드를 테스트하려면 간단히 컴파일하고 Arduino IDE를 사용하여 ESP32 보드에 업로드하십시오. 그런 다음 직렬 모니터를 열고 결과를 확인하십시오.

직렬 모니터에 인쇄되는 GET 요청의 응답을 보여주는 그림 7과 유사한 출력이 표시되어야 합니다. 이 콘텐츠는 우리가 웹 브라우저를 사용하여 웹사이트에 액세스할 때 얻는 것과 일치합니다.

그림 7  – HTTPS GET 요청의 출력.


참고문헌

[1]  https://www.instantssl.com/ssl-certificate-products/https.html

[2]  https://support.dnsimple.com/articles/what-is-ssl-root-certificate/


관련된 컨텐츠

'ESP32' 카테고리의 다른 글

ESP32 / ESP8266 Arduino: Using structs  (0) 2021.08.16
ESP32 Arduino: Software reset  (0) 2021.08.16
ESP32 / ESP8366 Arduino: Creating a simple class  (0) 2021.08.16
ESP32 Arduino: External interrupts  (0) 2021.08.16
ESP32 Arduino: Timer interrupts  (0) 2021.08.16