websocketpp wss

一. wss 认证

关于SSL认证说明(转载)https://www.cnblogs.com/bluestorm/p/10571989.html

二.从浏览器生成wss客户端
1.用谷歌打开网站

在这里插入图片描述

2.点击"小锁", 在证书路径中所有的证书都需要生成*.pem。


在这里插入图片描述

3.导出证书

选择第一级证书,点击查看证书>>详细信息>>复制到文件>>下一步>>选择DER 编码二进制X.509(.CER)>>下一步>>指定导出文件路径文件名(可直接导出到openssl的bin目录下),完成证书导出(文件后缀.cer)。

4.生成 .pem 文件

使用 openssl.exe 将证书文件转为.pem 文件,命令如下

openssl x509 -in xxx.cer -inform der -out xxx.pem

重复 2 3 4步骤依次将各级证书,全部生成对应的.pem文件。然后将各个.pem文件的内容copy到同一个.pem文件内(如client.pem)。
websocketpp/examples/print_client_tls/print_client_tls.cpp测试只生成一级目录证书,即可连接成功

5. websockets
  • websockets默认端口 443
  • 地址格式: wss://ip地址:443
三.websocketpp的wss client demo

修改 websocketpp/examples/print_client_tls/print_client_tls.cpp内容

/// Verify that one of the subject alternative names matches the given hostname
bool verify_subject_alternative_name(const char * hostname, X509 * cert)
{
    STACK_OF(GENERAL_NAME) * san_names = NULL;

    san_names = (STACK_OF(GENERAL_NAME) *) X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
    if (san_names == NULL) {
        return false;
    }

    int san_names_count = sk_GENERAL_NAME_num(san_names);

    bool result = false;

    for (int i = 0; i < san_names_count; i++) {
        const GENERAL_NAME * current_name = sk_GENERAL_NAME_value(san_names, i);

        if (current_name->type != GEN_DNS) {
            continue;
        }

        char * dns_name = (char *) ASN1_STRING_data(current_name->d.dNSName);

        // Make sure there isn't an embedded NUL character in the DNS name
        if ((size_t)ASN1_STRING_length(current_name->d.dNSName) != strlen(dns_name)) {
            break;
        }
        // Compare expected hostname with the CN
        result = (strcasecmp(hostname, dns_name) == 0);
    }
    sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free);

    return result;
}

/// Verify that the certificate common name matches the given hostname
bool verify_common_name(const char * hostname, X509 * cert)
{

    // Find the position of the CN field in the Subject field of the certificate
    int common_name_loc = X509_NAME_get_index_by_NID(X509_get_subject_name(cert), NID_commonName, -1);
    if (common_name_loc < 0) {
        return false;
    }

    // Extract the CN field
    X509_NAME_ENTRY * common_name_entry = X509_NAME_get_entry(X509_get_subject_name(cert), common_name_loc);
    if (common_name_entry == NULL) {
        return false;
    }

    // Convert the CN field to a C string
    ASN1_STRING * common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);
    if (common_name_asn1 == NULL) {
        return false;
    }

    char * common_name_str = (char *) ASN1_STRING_data(common_name_asn1);

    // Make sure there isn't an embedded NUL character in the CN
    if ((size_t)ASN1_STRING_length(common_name_asn1) != strlen(common_name_str)) {
        return false;
    }

    // Compare expected hostname with the CN
    return (strcasecmp(hostname, common_name_str) == 0);
}


bool verify_certificate(const char * hostname, bool preverified, boost::asio::ssl::verify_context& ctx)
{

    int depth = X509_STORE_CTX_get_error_depth(ctx.native_handle());

    if (depth == 0 && preverified) {
        X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());

        if (verify_subject_alternative_name(hostname, cert)) {
            return true;
        } else if (verify_common_name(hostname, cert)) {
            return true;
        } else {
            return false;
        }
    }

    return preverified;
}

context_ptr on_tls_init(const char * hostname, websocketpp::connection_hdl) {

    context_ptr ctx = websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::sslv23); 
    try {
        ctx->set_options(boost::asio::ssl::context::default_workarounds |
                         boost::asio::ssl::context::no_sslv2 |
                         boost::asio::ssl::context::no_sslv3 |
                         boost::asio::ssl::context::single_dh_use);
		// 注意此处:set_verify_mode
		//  选择 verify_peer	  需要  load_verify_file
		//  选择 verify_none   不需要  load_verify_file
        ctx->set_verify_mode(boost::asio::ssl::verify_peer);
        ctx->set_verify_callback(bind(&Mverify_certificate, hostname, ::_1, ::_2));
        
        // Here we load the CA certificates of all CA's that this client trusts.
        ctx->load_verify_file("client.pem");

    } catch (std::exception& e) {
        std::cout << e.what() << std::endl;
    }
    return ctx;
}
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值