下载 FreeRTOS
 

出色的 RTOS & 嵌入式软件

最新资讯
简化任何设备的身份验证云连接。
利用 CoAP 设计节能型云连接 IoT 解决方案。
11.0.0 版 FreeRTOS 内核简介:
FreeRTOS 路线图和代码贡献流程。
使用 FreeRTOS 实现 OPC-UA over TSN。

coreHTTP 演示(相互身份验证)

注意:我们建议在构建任何物联网 (IoT) 应用程序时始终使用相互身份验证。

单线程 VS 多线程

coreHTTP 有两种使用模式,一种是单线程式的,另一种是多线程式的 (多任务)。虽然此页面上的演示在线程中运行 HTTP 库,但它实际上是在演示如何在单线程环境(只有一个任务在演示中使用 HTTP API )中使用 coreHTTP。单线程应用程序必须重复调用 HTTP 库,而多线程应用程序则可以在代理(或守护进程)任务的后台执行发送 HTTP 请求。

演示简介

coreHTTP (相互身份验证)使用网络传输接口,该接口使用 mbedTLS 在运行 coreHTTP 的 IoT 设备客户端和远程 HTTP 服务器之间建立相互身份验证的连接。此演示可以连接到任何能够进行相互身份验证连接的 HTTP 服务器。连接后,演示创建 HTTP 请求,然后发送请求并接收响应。 下文介绍了如何连接到 Amazon Web Services (AWS) 的 IoT HTTP 服务器

共有两个示例项目逐一介绍“TLS 简介”页面上描述的概念,此示例项目是其中之一。第一个示例演示了未加密的 HTTP 通信。第二个示例(本页面上)在第一个示例的基础上引入强力相互身份验证(HTTP 服务器也会对其所连接的客户端进行身份验证)。

coreHTTP (相互身份验证)演示项目使用 FreeRTOS Windows 移植,从而可以在 Windows 上使用 Visual Studio 免费社区版本进行构建和评估,无需任何特定的 MCU 硬件。  

源代码组织

演示项目名为 http_mutual_auth_demo.sln,位于 主 FreeRTOS 下载内容FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/HTTP_Mutual_Auth 目录中(下载页面上也提供 Github 的链接)。 源代码的组织方式与基本 HTTP 演示(未使用 TLS )相同。

配置 HTTP 服务器连接

相互身份验证 HTTP 演示需要客户端身份验证和服务器身份验证。 由于大多数公共 HTTP 服务器不对客户端进行身份验证,因此本演示将介绍与 AWS (Amazon Web Services) IoT 的连接。还需要采取其他步骤,以采用 AWS 提供的现有工具获取和设置凭据。为了增强安全性, AWS IoT 不支持纯文本身份验证和仅服务器端身份验证。有关详细信息,请参阅 AWS 中的安全性页面。

请按照以下步骤配置与 AWS 的连接。

  1. 设置一个 Amazon Web Services (AWS) 帐户:
  2. 使用 AWS 身份和访问管理 (IAM) 设置帐户和权限。IAM 允许您管理每个用户的权限。默认情况下,用户需要获得根用户的授权才具有权限。
    • 要将 IAM 用户添加到您的 AWS 帐户,请参阅 IAM 用户指南
    • 通过添加以下策略,为您的 AWS 帐户设置访问 FreeRTOS 和 AWS IoT 的权限:
        • AmazonFreeRTOSFullAccess
        • AWSIoTFullAccess
    • 要将 AmazonFreeRTOSFullAccess 策略附加到您的 IAM 用户:

      1. 打开 IAM 控制台,然后在导航窗格中选择 Users
      2. 在搜索框中输入您的用户名,然后在搜索结果列表中选择它。
      3. 选择 Add permissions
      4. 选择 Attach existing policies directly
      5. 在搜索框中输入 AmazonFreeRTOS'FullAccess',然后从列表中选择 'Next: Review'
      6. 选择 Add permissions

      要将 AWSIoTFullAccess 策略附加到您的 IAM 用户:

      1. 打开 IAM 控制台,然后在导航窗格中选择 Users
      2. 在搜索框中输入您的用户名,然后在搜索结果列表中选择它。
      3. 选择 Add permissions
      4. 选择 Attach existing policies directly
      5. 在搜索框中输入 AWSIoT'FullAccess',然后从列表中选择 'Next: Review'
      6. 选择 'Add permissions'
  1. 使用 AWS IoT 核心控制台创建 AWS IoT 客户端证书。
      1. 将设备添加到 AWS IoT 控制台
        1. 按照以下步骤在 AWS IoT 中创建私钥和证书。立即下载创建的证书和私钥。您还需要通过以下步骤找到您的 AWS IoT 端点:
          1. 进入 AWS IoT 控制台
          2. 在导航窗格中,选择 'Settings'
          您的 AWS IoT 端点将显示为 定义端点。如下所示: <account-number>-ats.iot.<us-east-1>.amazonaws.com
      2. 在服务端完成设置后,您需要为客户端上的 AWS IoT 凭据配置凭据。将端点和凭据粘贴到:FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/HTTP_Mutual_Auth/demo_config.h
          1. AWS IoT 自定义端点复制到 #define democonfigAWS_IOT_ENDPOINT "<here>"
          2. 将从 AWS IoT 控制台下载的根 CA 证书复制到 #define democonfigROOT_CA_PEM "<here>" 。
          3. 将从 AWS IoT 控制台下载的客户端证书复制到 #define democonfigCLIENT_CERTIFICATE_PEM "<here>" 。
          4. 将从 AWS IoT 控制台下载的客户端私钥复制到 #define democonfigCLIENT_PRIVATE_KEY_PEM "<here>" 。

构建演示项目

此演示项目的构建方式与基本 HTTP 演示(未使用 TLS )相同。演示项目使用 Visual Studio 的免费社区版本。要构建演示,请执行如下操作:

  • 从 Visual Studio IDE 中打开 FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/HTTP_Mutual_Auth/http_mutual_auth_demo.sln Visual Studio 解决方案文件
  • 在 IDE 的 “Build” 菜单中选择 “Build Solution”
注意: 如果您使用的是 Microsoft Visual Studio 2017 或更早版本,则必须选择与您的版本兼容的平台工具集:Project -> RTOSDemos Properties -> Platform Toolset (项目- > RTOS 演示属性- >平台工具集)

功能

此演示提供与基本 HTTP 演示相同的功能,并增添了到您的 AWS IoT 端点的安全连接。 有关附加功能(创建 HTTP 请求、发送请求和接收响应)的详细信息,请查看基本 HTTP 演示(未使用 TLS )。

此演示创建了一个应用程序任务,展示如何连接到 AWS IoT HTTP 服务器,创建 HTTP 请求,发送 HTTP 请求并接收 HTTP 响应,最后断开与服务器的连接。此演示的结构体如下所示。


static void prvHTTPDemoTask( void * pvParameters )
{
/* The transport layer interface used by the HTTP Client library. */
TransportInterface_t xTransportInterface;
/* The network context for the transport layer interface. */
NetworkContext_t xNetworkContext = { 0 };
TlsTransportParams_t xTlsTransportParams = { 0 };
BaseType_t xIsConnectionEstablished = pdFALSE;

/* The user of this demo must check the logs for any failure codes. */
BaseType_t xDemoStatus = pdPASS;

/* Remove compiler warnings about unused parameters. */
( void ) pvParameters;

/* Set the pParams member of the network context with desired transport. */
xNetworkContext.pParams = &xTlsTransportParams

/**************************** Connect. ******************************/

/* Attempt to connect to the HTTP server. If connection fails, retry after a

* timeout. The timeout value will be exponentially increased until either the

* maximum number of attempts or the maximum timeout value is reached. The

* function returns pdFAIL if the TCP connection cannot be established with

* the server after configured number of attempts. */

xDemoStatus = connectToServerWithBackoffRetries( prvConnectToServer,
&xNetworkContext );

if( xDemoStatus == pdPASS )
{
/* Set a flag indicating that a TLS connection exists. */
xIsConnectionEstablished = pdTRUE;

/* Define the transport interface. */
xTransportInterface.pNetworkContext = &xNetworkContext
xTransportInterface.send = TLS_FreeRTOS_send;
xTransportInterface.recv = TLS_FreeRTOS_recv;
}
else
{
/* Log error to indicate connection failure after all

* reconnect attempts are over. */

LogError( ( "Failed to connect to HTTP server %.*s.",
( int32_t ) AWS_IOT_ENDPOINT_LENGTH,
democonfigAWS_IOT_ENDPOINT ) );
}

/*********************** Send HTTP request.************************/

if( xDemoStatus == pdPASS )
{
xDemoStatus = prvSendHttpRequest( &xTransportInterface,
HTTP_METHOD_POST,
( sizeof( HTTP_METHOD_POST ) - 1 ),
democonfigPOST_PATH,
( sizeof( democonfigPOST_PATH ) - 1 ) );
}

/**************************** Disconnect. ******************************/

/* Close the network connection to clean up any system resources that the

* demo may have consumed. */

if( xIsConnectionEstablished == pdTRUE )
{
/* Close the network connection. */
TLS_FreeRTOS_Disconnect( &xNetworkContext );
}

if( xDemoStatus == pdPASS )
{
LogInfo( ( "prvHTTPDemoTask() completed successfully. "
"Total free heap is %u.\r\n",
xPortGetFreeHeapSize() ) );
LogInfo( ( "Demo completed successfully.\r\n" ) );
}
}

连接到 HTTP 服务器(带相互身份验证)

函数 connectToServerWithBackoffRetries() 试图与 HTTP 服务器建立相互身份验证 TLS 连接。如果连接失败,则在超时后重试。超时值将呈指数增加,直到达到最大尝试次数或最大超时值。函数 BackoffAlgorithm_GetNextBackoff() 提供呈指数增长的超时值,并在达到最大尝试次数时返回 BackoffAlgorithmRetriesExhausted。如果在达到配置的尝试次数后仍无法将 TLS 连接到此服务器,则 connectToServerWithBackoffRetries() 返回失败状态。


BaseType_t connectToServerWithBackoffRetries( TransportConnect_t connectFunction,
NetworkContext_t * pxNetworkContext )
{
BaseType_t xReturn = pdFAIL;
/* Status returned by the retry utilities. */
BackoffAlgorithmStatus_t xBackoffAlgStatus = BackoffAlgorithmSuccess;
/* Struct containing the next backoff time. */
BackoffAlgorithmContext_t xReconnectParams;
uint16_t usNextBackoff = 0U;

assert( connectFunction != NULL );

/* Initialize reconnect attempts and interval */
BackoffAlgorithm_InitializeParams( &xReconnectParams,
RETRY_BACKOFF_BASE_MS,
RETRY_MAX_BACKOFF_DELAY_MS,
RETRY_MAX_ATTEMPTS );

/* Attempt to connect to the HTTP server. If connection fails, retry after a

* timeout. The timeout value will exponentially increase until either the

* maximum timeout value is reached or the set number of attempts are

* exhausted.*/

do
{
xReturn = connectFunction( pxNetworkContext );

if( xReturn != pdPASS )
{
LogWarn( ( "Connection to the HTTP server failed. "
"Retrying connection with backoff and jitter." ) );
LogInfo( ( "Retry attempt %lu out of maximum retry attempts %lu.",
( xReconnectParams.attemptsDone + 1 ),
RETRY_MAX_ATTEMPTS ) );

/* Generate a random number and calculate backoff value (in milliseconds) for

* the next connection retry.

* Note: It is recommended to seed the random number generator with a device-specific

* entropy source so that possibility of multiple devices retrying failed network operations

* at similar intervals can be avoided. */

xBackoffAlgStatus = BackoffAlgorithm_GetNextBackoff( &xReconnectParams, uxRand(), &usNextBackoff );
}
} while( ( xReturn == pdFAIL ) && ( xBackoffAlgStatus == BackoffAlgorithmSuccess ) );

if( xReturn == pdFAIL )
{
LogError( ( "Connection to the server failed, all attempts exhausted." ) );
}

return xReturn;
}

函数 prvConnectToServer() 演示了如何与服务器建立 HTTP 连接。它使用 TLS 传输接口,该接口在文件 FreeRTOS-Plus/Source/Application-Protocols/network_transport/freertos_plus_tcp/using_mbedtls/using_mbedtls.c 中实现。prvConnectToServer() 的定义如下。


static BaseType_t prvConnectToServer( NetworkContext_t * pxNetworkContext )
{
BaseType_t xStatus = pdPASS;

TlsTransportStatus_t xNetworkStatus;
NetworkCredentials_t xNetworkCredentials = { 0 };

configASSERT( pxNetworkContext != NULL );

if( democonfigAWS_HTTP_PORT == 443 )
{
/* ALPN protocols must be a NULL-terminated list of strings. Therefore,

* the first entry will contain the actual ALPN protocol string while the

* second entry must remain NULL. */

static const char * pcAlpnProtocols[] = { IOT_CORE_ALPN_PROTOCOL_NAME, NULL };
xNetworkCredentials.pAlpnProtos = pcAlpnProtocols;
}

xNetworkCredentials.disableSni = democonfigDISABLE_SNI;
/* Set the credentials for establishing a TLS connection. */
xNetworkCredentials.pRootCa = ( const unsigned char * ) democonfigROOT_CA_PEM;
xNetworkCredentials.rootCaSize = sizeof( democonfigROOT_CA_PEM );
xNetworkCredentials.pClientCert = ( const unsigned char * ) democonfigCLIENT_CERTIFICATE_PEM;
xNetworkCredentials.clientCertSize = sizeof( democonfigCLIENT_CERTIFICATE_PEM );
xNetworkCredentials.pPrivateKey = ( const unsigned char * ) democonfigCLIENT_PRIVATE_KEY_PEM;
xNetworkCredentials.privateKeySize = sizeof( democonfigCLIENT_PRIVATE_KEY_PEM );

/* Establish a TLS session with the HTTP server. This example connects to

* the HTTP server as specified in democonfigAWS_IOT_ENDPOINT and

* democonfigAWS_HTTP_PORT in demo_config.h. */

LogInfo( ( "Establishing a TLS session to %.*s:%d.",
( int32_t ) AWS_IOT_ENDPOINT_LENGTH,
democonfigAWS_IOT_ENDPOINT,
democonfigAWS_HTTP_PORT ) );

/* Attempt to create a mutually authenticated TLS connection. */
xNetworkStatus = TLS_FreeRTOS_Connect( pxNetworkContext,
democonfigAWS_IOT_ENDPOINT,
democonfigAWS_HTTP_PORT,
&xNetworkCredentials,
democonfigTRANSPORT_SEND_RECV_TIMEOUT_MS,
democonfigTRANSPORT_SEND_RECV_TIMEOUT_MS );

if( xNetworkStatus != TLS_TRANSPORT_SUCCESS )
{
xStatus = pdFAIL;
}

return xStatus;
}
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.