如何通过SignalR-Client-Cpp使用Windows证书存储中的客户端证书建立连接
解决SignalR-C++客户端使用Windows证书存储证书完成客户端认证的问题
问题根源
报错WinHttpSendRequest: 12044说明WinHTTP在建立TLS连接时,服务器要求客户端提供证书,但你的客户端未指定可用证书。SignalR-Client-Cpp底层依赖WinHTTP实现网络通信,因此需要通过WinHTTP的证书选择回调,从Windows证书存储中筛选并返回符合要求的证书。
具体实现步骤
1. 实现WinHTTP证书选择回调函数
该函数会被WinHTTP调用,用于从系统证书存储中挑选适配的客户端证书。你可以根据证书的主题、颁发者、有效期或服务器名称等属性做精准筛选:
#include <winhttp.h> #include <wincrypt.h> #pragma comment(lib, "winhttp.lib") #pragma comment(lib, "crypt32.lib") DWORD WINAPI ClientCertSelectionCallback( IN DWORD dwCertEncodingType, IN PCCERT_CONTEXT pCertContext, IN PCCERT_CHAIN_CONTEXT pCertChainContext, IN LPWSTR pwszServerName, IN DWORD dwServerNameLen, IN DWORD_PTR dwContext ) { // 示例:筛选主题包含指定关键词的证书(实际场景按需调整逻辑) WCHAR subjectName[256] = {0}; if (CertGetNameStringW(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nullptr, subjectName, ARRAYSIZE(subjectName))) { if (wcsstr(subjectName, L"Your-Client-Cert-Subject") != nullptr) { return S_OK; // 选中该证书 } } return WINHTTP_NO_CLIENT_CERT; // 无匹配证书,终止连接 }
2. 配置SignalR HTTP客户端并关联回调
SignalR的hub_connection基于http_client构建,需要给http_client的底层WinHTTP会话注册上述回调:
#include <signalrclient/hub_connection.h> #include <signalrclient/http_client.h> int main() { // 初始化HTTP客户端配置 web::http::client::http_client_config config; // 获取WinHTTP会话句柄(强制转换,SignalR-C++底层用WinHTTP实现) HINTERNET hSession = reinterpret_cast<HINTERNET>(config.handle()); // 启用客户端证书选择功能 if (!WinHttpSetOption(hSession, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, nullptr, 0)) { // 处理配置失败逻辑,比如打印GetLastError()信息 return 1; } // 注册证书选择回调 if (!WinHttpSetCallback( hSession, reinterpret_cast<WINHTTP_STATUS_CALLBACK>(ClientCertSelectionCallback), WINHTTP_CALLBACK_FLAG_SECURITY_CLIENT_AUTH_CERT, 0 )) { // 处理回调注册失败逻辑 return 1; } // 创建并启动SignalR连接 auto connection = signalr::hub_connection::create(L"https://your-server-domain/hub-path", config); connection->start().wait(); // 后续业务逻辑... return 0; }
3. 关键注意事项
- 确保程序具备访问Windows证书存储的权限:客户端证书通常存放在「当前用户-个人」存储区,普通用户权限即可访问,若证书在「本地计算机」存储区则需要管理员权限。
- 验证证书有效性:打开
certmgr.msc确认证书未过期、未被吊销,且「增强密钥用法」包含客户端认证(1.3.6.1.5.5.7.3.2)。
排查要点
- 若回调未触发:用浏览器访问SignalR Hub地址,确认服务器是否真的要求客户端证书(浏览器会弹出证书选择窗口)。
- 选证书后仍报错:检查服务器是否信任该证书的颁发机构,或证书的密钥用法是否符合服务器要求。
内容的提问来源于stack exchange,提问作者pepece
相关产品推荐
相关产品推荐

