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

gsoap 2.8.116版本加密XML SOAP消息时无法加密SOAP:Body问题求助

问题解决方案

根因说明

gsoap 2.8.100及以上版本对WS-Security模块做了两处不兼容升级:

  • 移除了添加EncryptedKey后默认加密SOAP Body的逻辑,必须显式指定需要加密的元素
  • 命名空间前缀匹配规则更严格,旧版宽松的前缀匹配规则被取消,元素注册和引用的前缀必须和实际生成的SOAP消息前缀完全一致
  • 重复的签名规则注册会导致元素ID标记冲突,进而加密逻辑跳过目标元素

修正步骤

1. 调整签名逻辑,移除重复的Body签名声明

旧代码中同时调用soap_wsse_sign_body和soap_wsse_sign_only("SOAP-ENV:Body")会重复注册Body的wsu:Id,导致后续加密逻辑无法识别Body元素,直接删除soap_wsse_sign_only调用即可。

2. 显式指定要加密的SOAP Body元素

添加EncryptedKey后,需要额外调用soap_wsse_add_EncryptedData显式指定加密SOAP Body,同时确认命名空间前缀和你实际gsoap生成代码的SOAP信封前缀一致(如果你的代码中SOAP Body前缀是soapenv就替换为对应值)。

3. 修正后的完整代码片段

int main() {
    // 确认此处的SOAP-ENV前缀和你实际生成的SOAP消息Body前缀一致,若为soapenv则替换
    soap_wsse_set_wsu_id(( * proxy) -> soap, "wsse:BinarySecurityToken SOAP-ENV:Body");

    if (soap_wsse_add_BinarySecurityTokenX509(( * proxy) -> soap, "X509Token", * cert1) ||
        soap_wsse_add_KeyInfo_SecurityTokenReferenceX509(( * proxy) -> soap, "#X509Token") ||
        soap_wsse_sign_body(( * proxy) -> soap, SOAP_SMD_SIGN_RSA_SHA256, * pkey1, 0)) {
        return (3);
    }

    char * token1, * token2;
    if (cfg.isEncryptionEnabled) {
        for (int i = 0; i < sk_X509_num( * ca); i++) {
            char subj[1024];
            X509_NAME_oneline(X509_get_subject_name(sk_X509_value( * ca, i)), subj, sizeof(subj));
            for (token1 = strtok_r(subj, "=", & token2); token1; token1 = strtok_r(NULL, "=", & token2)) {
                if (strcmp(SERVER_PUBLIC_KEY_NAME, token1) == 0) {
                    if (soap_wsse_add_EncryptedKey(( * proxy) -> soap, SOAP_MEC_AES256_CBC, "Cert", sk_X509_value( * ca, i), NULL, NULL, NULL)
                        // 新增:显式指定加密SOAP Body,用生成的EncryptedKey对应的对称密钥加密
                        || soap_wsse_add_EncryptedData(( * proxy) -> soap, SOAP_MEC_AES256_CBC, "SOAP-ENV:Body", "#Cert", NULL)) {
                        return (4);
                    }
                }
            }
        }
    }

    int check = soap_write_ns2__RequestMessage(proxy -> soap, ns2__requestMessage);
    proxy -> soap -> os = NULL;
    proxy -> soap_endpoint = cfg.serverURL;

    int status = runTransaction(ns2__requestMessage, ** ns2__replyMessage);
}

验证要点

如果修改后还是无法加密,可先打印生成的SOAP原始消息:

  • 确认SOAP Body标签上是否有wsu:Id="SOAP-ENV:Body"属性
  • 确认EncryptedData节点的ReferenceList中是否有指向Body ID的引用

内容的提问来源于stack exchange,提问作者rohit kesarvani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 21:36:02