aprendizaje de la mangosta (1) comunicación Https

Prefacio

El artículo anterior registró el uso de mangosta para la comunicación http. Originalmente planeado para comunicarse más con https, pero finalmente solo construyó exitosamente un servidor https, al que se puede acceder a través de la solicitud https del navegador; pero el cliente https escrito por mí no puede comunicarse exitosamente con el servidor.
(El nivel del editor es limitado, perdóname, primero registra algo de la experiencia de construir un servidor https ヾ ( ̄ □  ̄;) ノ)

Configurar la biblioteca opessl

Para configurar la compatibilidad con HTTPS, debe utilizar la biblioteca OpenSSL,

Por supuesto, también puede usar gmssl (porque gmssl puede reemplazar a openssl). Pero esto no significa que se puedan utilizar conjuntos de cifrado en gmssl. Mongoose solo admite conjuntos de cifrado en openssl y no admite conjuntos de cifrado específicos de gmssl. La razón es la siguiente:
Inserte la descripción de la imagen aquí
del código fuente de mangosta, se puede ver que usa SSLv23_client_method / SSLv23_server_method al construir el contexto, y para gmssl, debería usar GMTLS_client_method / GMTLS_server_method ... por lo que no puede admitir gmtls.
---------------------------------- De acuerdo, lo anterior es una digresión --------- - ---------------------------------

Volviendo al tema, necesitamos compilar la biblioteca openssl / gmssl. El editor ha compilado la biblioteca gmssl (libcrypto.lib, libssl.lib) antes, y escribió artículos relacionados sobre cómo compilar, así que simplemente "la usaré "aquí. Para entrar en más detalles, los zapatos de los niños pueden encontrar la información y compilarla por sí mismos ... (σ ° ∀ °) σ ...
Introduzca la biblioteca gmssl (archivo de encabezado de enlace y archivo .lib, etc.) en el proyecto, de modo que se configure la biblioteca openssl.
(Nota: el editor es una prueba de codificación realizada en la plataforma Windows)

Habilitar la función SSL

La función ssl predeterminada de mangosta está desactivada, por lo que primero debemos activar la función ssl.
El método de apertura es el siguiente: (Nota. El editor usa la versión 6.13 de
mangosta ) mangosta define la macro MG_ENABLE_SSL para controlar la apertura y cierre de la función ssl. Modifique el valor de MG_ENABLE_SSL en el archivo de encabezado mongoose.h a 1 para habilitar la función SSL.
Inserte la descripción de la imagen aquí

código

Servidor

El proceso de construcción del servidor https es similar a http y también sigue la lógica básica del servidor. La diferencia es que necesita usar la función mg_bind_opt para crear una conexión de monitoreo. El parámetro struct mg_bind_opts opts en la función mg_bind_opts se usa para especificar el certificado, la clave privada y otros parámetros requeridos para la comunicación ssl.
Inserte la descripción de la imagen aquí
El código completo del servidor es el siguiente:

#include "stdafx.h"
#include "stdafx.h"
#include "mongoose.h"

#include <string>

static const char *s_http_port = "8443";
static const char *s_ssl_cert = "server.crt";
static const char *s_ssl_key = "server.key";
static const char *s_ssl_ca = "ca.crt";
static struct mg_serve_http_opts s_http_server_opts;

static void ev_handler(struct mg_connection *conn, int ev, void *ev_data)
{
    
    
	// 区分http和websocket
	if (ev == MG_EV_HTTP_REQUEST)
	{
    
    
		http_message *hm = (http_message *)ev_data;

		//(int)hm->message.len, hm->message.p 中存放客户端发过来的信息,包括post,Host(http地址),Content-Length(信息的长度),以及信息本身。
		//通过 std::string url = std::string(hm->uri.p, hm->uri.len); 可以得到url
		//通过 std::string body = std::string(hm->body.p, hm->body.len);可以得到body中 存储的从客户端发送过来的信息
		std::string req_str = std::string(hm->message.p, hm->message.len);
		printf("got request:\n%s\n", req_str.c_str());

		//TODO.  请求处理
		// eg.  We have received an HTTP request. Parsed request is contained in `hm`.
		//      Send HTTP reply to the client which shows full original request.
		mg_send_head(conn, 200, hm->message.len, "Content-Type: text/plain");
		mg_printf(conn, "%.*s", (int)hm->message.len, hm->message.p);

		//API函数mg_serve_http()可以轻松地从文件系统提供文件。 例如,为了创建一个从当前目录提供静态文件的Web服务器,实现如下处理:
		//mg_serve_http(conn, hm, s_http_server_opts);

	}
	else if (ev == MG_EV_WEBSOCKET_HANDSHAKE_DONE ||
		ev == MG_EV_WEBSOCKET_FRAME ||
		ev == MG_EV_CLOSE)
	{
    
    
		websocket_message *ws_message = (struct websocket_message *)ev_data;
		//TODO.  请求处理
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
    
    
	//声明和初始化事件管理器,  mg_mgr是拥有所有活动连接的事件管理器
	struct mg_mgr mgr;
	//mg_connection描述连接
	struct mg_connection *nc;

	struct mg_bind_opts bind_opts;
	const char *err;

	mg_mgr_init(&mgr, NULL);

	/* Set HTTP server options */
	memset(&bind_opts, 0, sizeof(bind_opts));
	bind_opts.error_string = &err;      //
	bind_opts.ssl_cert = s_ssl_cert;    //指定服务端证书
	bind_opts.ssl_key = s_ssl_key;      //指定服务端私钥
	//bind_opts.ssl_ca_cert = s_ssl_ca;  //提供了CA证书,表示需要验证客户端的证书

	printf("Starting SSL server on port %s, cert from %s, key from %s\n", s_http_port, bind_opts.ssl_cert, bind_opts.ssl_key);
	nc = mg_bind_opt(&mgr, s_http_port, ev_handler, bind_opts);
	if (nc == NULL)
	{
    
    
		printf("Failed to create listener: %s\n", err);
		getchar();
		return 1;
	}
	// Set up HTTP server parameters,  for both http and websocket
	mg_set_protocol_http_websocket(nc);
	s_http_server_opts.document_root = ".";  // Serve current directory
	s_http_server_opts.enable_directory_listing = "yes";

	//通过调用循环创建一个事件mg_mgr_poll()循环:
	for (;;) {
    
    
		mg_mgr_poll(&mgr, 1000);
	}
	mg_mgr_free(&mgr);

	return 0;
}

Resultado de la ejecución: (En el código, devolvemos directamente la solicitud recibida al cliente)
Inserte la descripción de la imagen aquí

Si el certificado de CA se especifica mediante bind_opts.ssl_ca_cert , significa que el servidor necesita verificar el certificado del cliente, en este momento el cliente debe proporcionar su certificado al acceder, de lo contrario no se puede establecer la conexión con el servidor.
Dado que usamos certificados autogenerados aquí, no podemos acceder a ellos directamente desde el navegador.
Inserte la descripción de la imagen aquí

Cliente

En teoría, el proceso de implementación del cliente también debería ser similar a http y también seguir la lógica básica del servidor. La diferencia es que si el servidor necesita autenticar la identidad del cliente, necesita configurar parámetros a través de funciones como mg_connect_http_opt / mg_connect_opt.

Lo ideal es completo y la realidad es cruel. ╮ (︶﹏︶ ") ╭El fantasma sabe lo que he experimentado
. El cliente no puede conectarse al servidor cuando se realiza la codificación real. El seguimiento de depuración encontró que se activó la señal MG_EV_CONNECT en ev_handler, pero se obtuvo connect_status. El valor de estado es -3.
… (• ิ _ • ิ)? Aún no se ha encontrado el motivo. El contenido de la conexión del cliente https se actualizará más tarde.
Si sabe, por favor deje un comentario y deje que el editor.

Supongo que te gusta

Origin blog.csdn.net/lt4959/article/details/112987047
Recomendado
Clasificación