65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 WinHTTP 进行一次性 SSL 证书注册

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.53/5 (8投票s)

2008年2月29日

CPOL

1分钟阅读

viewsIcon

55944

downloadIcon

1365

从远程网页浏览器注册自签名 SSL 证书。

引言

你是否曾经需要从“远程”网页浏览器中将自签名证书安装到 IE 证书缓存中?这里有一些示例代码,或许可以使事情变得更容易。

背景

HTTPS 测试通常会很麻烦。每次浏览到你的测试 Web 服务器时,都会出现一个挑战对话框,SSL 证书已过期等等。接下来,你希望其他人测试你的应用程序。理想情况下,他们可以运行一个自注册程序来简化操作。

使用代码

代码很简单。步骤也很简单。打开到 Web 服务器的 HTTPS 连接,获取 SSL 证书,并将证书安装到证书缓存中。提供的代码依赖于 Windows HTTP Services 接口以及一些 Cryptography API 调用。函数 CwinHttpsCertDlg::Register() 打开一个 WinHTTP 会话,创建连接并发送请求。此时,我们查询请求以获取证书。然后将证书放置在证书存储区中。

注意:为了这个示例代码的需要,证书被放置在“根”存储区中。请小心将证书添加到你的缓存中,并在测试完成后将其删除。保护你的密钥!

以下是一些从 Web 服务器“获取”证书的代码片段

    DWORD dwFlags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID|
        SECURITY_FLAG_IGNORE_CERT_DATE_INVALID|
        SECURITY_FLAG_IGNORE_UNKNOWN_CA;

        // open a session handle
    hSession = WinHttpOpen( szUserAgent,
        WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
        WINHTTP_NO_PROXY_NAME,
        WINHTTP_NO_PROXY_BYPASS, 0 );

    // connect to a web server
    hConnect = WinHttpConnect( hSession,
        m_csServer,
        INTERNET_DEFAULT_HTTPS_PORT,
        0 );

    // open a request handle
    hRequest = WinHttpOpenRequest( hConnect,
        L"GET",
        L"",
        NULL,
        WINHTTP_NO_REFERER,
        WINHTTP_DEFAULT_ACCEPT_TYPES,
        WINHTTP_FLAG_SECURE ); 

    // important - set security to ignore 'bad' certs
    bRet = WinHttpSetOption(
        hRequest,
        WINHTTP_OPTION_SECURITY_FLAGS,
        &dwFlags,
        sizeof(DWORD)
    );

    // send the request
    bRet = WinHttpSendRequest( hRequest,
        WINHTTP_NO_ADDITIONAL_HEADERS,
        0,
        WINHTTP_NO_REQUEST_DATA,
        0,
        0,
        0 );

    // get a handle on the certificate
    bRet = WinHttpQueryOption(
        hRequest,
        WINHTTP_OPTION_SERVER_CERT_CONTEXT,
        &pCert,
        &dwLen
    );

现在我们获得了证书的句柄,将证书加载到存储区中

    // open a certificate store
     hCertStore = CertOpenStore( CERT_STORE_PROV_SYSTEM,
        0,
        0,
        CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE,
        L"Root"); 

    // add the certificate
    bRet =  CertAddCertificateContextToStore(
        hCertStore,
        pCert,
        CERT_STORE_ADD_REPLACE_EXISTING,
        NULL
    );

    // release the certificate
    CertFreeCertificateContext(pCert);

    // close the store
    bRet = CertCloseStore( hCertStore, 0 );

最后,你可能可以使用以下脚本生成证书。这是一个带有 OpenSSL 的 *NIX 盒子上的 *bash* 脚本。

    #!/bin/bash

    #Generate ssl certificate
    PREFIX="foxbat.swiftview.com"

    #cd /opt/apache/conf
    mkdir ssl
    cd ssl
    openssl genrsa 1024 > ${PREFIX}.key
    chmod 600 ${PREFIX}.key
    openssl req -new -key ${PREFIX}.key  > ${PREFIX}.csr
    openssl req -x509 -days 365 -key ${PREFIX}.key -in ${PREFIX}.csr  > ${PREFIX}.crt
    echo "Add the following lines to httpd.conf"
    echo "SSLCertificateFile /opt/apache/conf/ssl/${PREFIX}.crt"
    echo "SSLCertificateKeyFile /opt/apache/conf/ssl/${PREFIX}.key"

certs.png

关注点

这段代码的一个令人烦恼的问题是,Platform SDK 不包含 libs 的 WinHTTP 头文件。你需要安装较新版本的 SDK 才能正确编译此代码。

© . All rights reserved.