You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 02:06:27