Node.js中SOAP请求同时配置TLS与WSS双重安全的问题咨询
解答
node-soap 库的 client.setSecurity() 方法默认仅支持绑定一个安全实例,重复调用会直接覆盖前序配置,因此先后传入TLS安全实例和WSS安全实例必然会导致其中一个失效。
实现方案
方案1:请求层注入TLS配置(最简单,推荐)
TLS属于传输层安全,不需要通过setSecurity方法配置,直接将PFX证书参数注入HTTP请求配置即可,setSecurity仅用来配置WSS消息层安全。
注意旧版本node-soap在createClient顶层options中传入的pfx、passphrase仅会用于拉取WSDL文件的请求,不会自动继承到后续业务SOAP请求中,需要明确指定请求配置,必要时可以重写httpClient方法兜底:
const soap = require('soap'); const fs = require('fs'); // 预加载所有证书文件 const tlsPfx = fs.readFileSync("[cert-tls.p12]"); const tlsPassphrase = "[password]"; const wssPrivateKey = fs.readFileSync("[privateKey.pem]"); const wssPublicKey = fs.readFileSync("[publickey.pem]"); const wssPassphrase = "[password]"; const clientOptions = { endpoint: endpoint, // 拉取WSDL阶段的TLS配置 wsdl_options: { pfx: tlsPfx, passphrase: tlsPassphrase }, // 后续业务请求的默认TLS配置 requestOptions: { pfx: tlsPfx, passphrase: tlsPassphrase } }; soap.createClient(url, clientOptions, function (err, client) { if (err) { console.log("客户端创建失败", err); return; } // 仅配置WSS消息层安全 const wssSecurity = new soap.WSSecurityCert(wssPrivateKey, wssPublicKey, wssPassphrase); client.setSecurity(wssSecurity); // 兜底:兼容部分版本requestOptions不生效的问题,强制给所有请求注入TLS配置 const originRequest = client.httpClient.request; client.httpClient.request = function(reqUrl, data, callback, extraHeaders, extraOptions) { extraOptions = extraOptions || {}; extraOptions.pfx = tlsPfx; extraOptions.passphrase = tlsPassphrase; return originRequest.call(this, reqUrl, data, callback, extraHeaders, extraOptions); }; client.ObslugaRecepty.ObslugaReceptyWS.zapisPakietuRecept( recepta_podpisana, function (err, result) { if (err) { console.log("请求失败", err); return; } console.log("请求成功", result); } ); });
方案2:自定义组合安全类
如果要完全遵循setSecurity的配置逻辑,可以自定义一个组合安全类,内部同时调用TLS和WSS两个安全实例的对应方法,再传入setSecurity:
// 组合安全类 class CombinedSecurity { constructor(tlsSec, wssSec) { this.tlsSec = tlsSec; this.wssSec = wssSec; } // 给请求添加配置项(TLS逻辑在这里执行) addOptions(options) { this.tlsSec.addOptions(options); this.wssSec.addOptions(options); } // 生成SOAP安全头XML(WSS逻辑在这里执行) toXML() { return this.wssSec.toXML(); } // 添加请求头 addHeaders(headers) { this.wssSec.addHeaders(headers); } } // 使用示例 soap.createClient(url, {}, function(err, client) { if (err) throw err; const tlsSec = new soap.ClientSSLSecurityPFX(tlsPfx, tlsPassphrase); const wssSec = new soap.WSSecurityCert(wssPrivateKey, wssPublicKey, wssPassphrase); // 传入组合后的安全实例,不会互相覆盖 client.setSecurity(new CombinedSecurity(tlsSec, wssSec)); // 后续业务调用逻辑不变 })
关键说明
- TLS/SSL是HTTPS握手阶段的传输层校验,WS-Security是SOAP报文层面的消息层校验,两者作用层级不同,不存在互斥,只是
node-soap默认没有提供多安全实例绑定能力,手动组合逻辑即可。 - 初始代码中PFX配置不生效的核心原因是旧版本库的配置隔离:顶层options中的证书配置仅用于WSDL拉取请求,不会透传给后续业务接口请求。
内容的提问来源于stack exchange,提问作者Damian Łaguna
相关产品推荐
相关产品推荐

