我正在研究安全Web服务之间的互操作性。安全性必须仅在消息级别上完成。到目前为止,我已经设法使用证书使WCF和WSIT / Metro协同工作。现在我正在尝试使用gSoap做同样的事情,但到目前为止我没有运气。
我已经成功地使用wsdl2h从Java服务WSDL生成头文件,并且我能够使用soapcpp2生成必要的类。通过遵循gsoap文档,WSSE和WSA插件应该正确配置,如果我在Wireshark中进行一些嗅探,我看到Gsoap客户端发送带有安全头和WS-Addressing的请求字段(To,Action,MessageID,ReplyTo)。
Java服务配置为使用3DES算法,用户名认证令牌和Lax安全标头布局,使用带有对称密钥的用户名认证。
证书位于Glassfish密钥库和信任库中,并已导出并转换为PEM文件,以便在gSoap中使用。
这是我的C ++应用程序代码:
#include <cstdlib>
#include <iostream>
#include "soapNewWebServicePortBindingProxy.h"
#include "NewWebServicePortBinding.nsmap"
#include "wsseapi.h"
#include "wsaapi.h"
using namespace std;
/*
*
*/
int main(int argc, char** argv) {
static char DES_KEY[20] =
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
/* SET UP */
NewWebServicePortBinding proxy;
proxy.soap = soap_new1(SOAP_XML_CANONICAL | SOAP_XML_INDENT);
soap_register_plugin(proxy.soap, soap_wsa);
soap_register_plugin(proxy.soap, soap_wsse);
ns1__hello req;
ns1__helloResponse resp;
req.name = new std::string("derpenstein");
/* ADD WS-SECURITY ELEMENTS */
soap_wsse_add_Security(proxy.soap);
soap_wsse_add_Signature(proxy.soap);
soap_wsse_add_Timestamp(proxy.soap, NULL, 300);
//OpenSSL_add_all_algorithms();
FILE *fd = fopen("gsoappublic.pem", "r");
FILE *fpriv = fopen("gsoapprivate.pem", "r");
X509 *cert = PEM_read_X509(fd, NULL, NULL, NULL);
EVP_PKEY *privkey = NULL;
EVP_PKEY *pubkey = NULL;
privkey = PEM_read_PrivateKey(fpriv, NULL, NULL, (void*)"changeit");
if (!privkey) {
cout << "error getting private key" << endl;
ERR_print_errors_fp(stderr);
return -1;
}
pubkey = X509_get_pubkey(cert);
if (!pubkey) {
cout << "error getting public key from certificate" << endl;
}
fclose(fd);
fclose(fpriv);
if (soap_wsse_encrypt_body(proxy.soap, SOAP_MEC_ENC_DES_CBC, DES_KEY, sizeof(DES_KEY))
|| soap_wsse_add_EncryptedKey(proxy.soap, "Cert", cert, NULL)
|| soap_wsse_add_UsernameTokenText(proxy.soap, "User", "test", "test")
|| soap_wsse_sign_body(proxy.soap, SOAP_SMD_SIGN_RSA_SHA1, privkey, 0)
|| soap_wsse_add_BinarySecurityTokenX509(proxy.soap, "X509Token", cert)
|| soap_wsse_add_KeyInfo_SecurityTokenReferenceX509(proxy.soap, "#X509Token")){
soap_print_fault(proxy.soap, stderr);
}
/* ADD WS-ADDRESSING */
soap_wsse_set_wsu_id(proxy.soap, "wsa5:From wsa5:To wsa5:ReplyTo wsa5:FaultTo wsa5:Action");
if (soap_wsa_request(proxy.soap, "uuid:5012354ad", "http://belgianguypc:8080/NewSecureService/NewWebService", "http://newsec.mince.org/NewWebService/helloRequest")
|| soap_wsa_add_ReplyTo(proxy.soap, "http://www.w3.org/2005/08/addressing/anonymous")) {
soap_print_fault(proxy.soap, stderr);
}
/* MAKE THE CALL */
int err = proxy.__ns1__hello(&req, &resp);
if (err == SOAP_OK) {
cout << "Success!";
cout << resp.return_;
}
else {
cout << "When sending:" << endl;
soap_print_fault(proxy.soap, stderr);
return -1;
}
return 0;
}
据我所知,我正在做的是添加时间戳,证书,用户名和密码,然后我用虚拟DES密钥对身体进行加密,然后使用我自己的私钥对消息进行签名。然后我打电话......
然而这不起作用,我得到的输出是:
When sending:
SOAP 1.1 Fault: wsse:FailedCheck [no subcode]
"WSS1927: Error occurred while decrypting EncryptedKey"
Detail: [no detail]
GlassFish提供堆栈跟踪:
SEVERE: WSS1913: Key used to decrypt EncryptedKey cannot be null
SEVERE: WSS1927: Error occured while decrypting EncryptedKey
SEVERE: WSITPVD0035: Error in Verifying Security in Inbound Message.
com.sun.xml.wss.impl.WssSoapFaultException: WSS1927: Error occured while decrypting EncryptedKey
at com.sun.xml.ws.security.opt.impl.util.SOAPUtil.newSOAPFaultException(SOAPUtil.java:158)
at com.sun.xml.ws.security.opt.impl.incoming.EncryptedKey.getKey(EncryptedKey.java:354)
at com.sun.xml.ws.security.opt.impl.incoming.KeySelectorImpl.resolveDirectReference(KeySelectorImpl.java:628)
at com.sun.xml.ws.security.opt.impl.incoming.processor.SecurityTokenProcessor.processDirectReference(SecurityTokenProcessor.java:267)
at com.sun.xml.ws.security.opt.impl.incoming.processor.SecurityTokenProcessor.resolveReference(SecurityTokenProcessor.java:143)
at com.sun.xml.ws.security.opt.impl.incoming.processor.KeyInfoProcessor.processKeyInfo(KeyInfoProcessor.java:152)
at com.sun.xml.ws.security.opt.impl.incoming.processor.KeyInfoProcessor.getKey(KeyInfoProcessor.java:132)
at com.sun.xml.ws.security.opt.impl.incoming.EncryptedData.process(EncryptedData.java:156)
at com.sun.xml.ws.security.opt.impl.incoming.EncryptedData.<init>(EncryptedData.java:113)
at com.sun.xml.ws.security.opt.impl.incoming.SecurityRecipient.createMessage(SecurityRecipient.java:791)
at com.sun.xml.ws.security.opt.impl.incoming.SecurityRecipient.validateMessage(SecurityRecipient.java:232)
at com.sun.xml.wss.provider.wsit.WSITServerAuthContext.verifyInboundMessage(WSITServerAuthContext.java:586)
at com.sun.xml.wss.provider.wsit.WSITServerAuthContext.validateRequest(WSITServerAuthContext.java:360)
at com.sun.xml.wss.provider.wsit.WSITServerAuthContext.validateRequest(WSITServerAuthContext.java:263)
at com.sun.enterprise.security.webservices.CommonServerSecurityPipe.processRequest(CommonServerSecurityPipe.java:173)
at com.sun.enterprise.security.webservices.CommonServerSecurityPipe.process(CommonServerSecurityPipe.java:144)
at com.sun.xml.ws.api.pipe.helper.PipeAdapter.processRequest(PipeAdapter.java:119)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:641)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:600)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:585)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:482)
at com.sun.xml.ws.server.WSEndpointImpl$2.process(WSEndpointImpl.java:314)
at com.sun.xml.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:608)
at com.sun.xml.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:259)
at com.sun.xml.ws.transport.http.servlet.ServletAdapter.handle(ServletAdapter.java:162)
at org.glassfish.webservices.JAXWSServlet.doPost(JAXWSServlet.java:145)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1539)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98)
at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:330)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:232)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:828)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:725)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
at java.lang.Thread.run(Unknown Source)
Caused by: java.io.IOException: Key used to decrypt EncryptedKey cannot be null
at com.sun.xml.ws.security.opt.impl.enc.CryptoProcessor.decryptKey(CryptoProcessor.java:346)
at com.sun.xml.ws.security.opt.impl.incoming.EncryptedKey.getKey(EncryptedKey.java:351)
... 51 more
我认为问题的根源是EncryptedKey根据服务为空,但我不知道它将是哪个键或为什么它将为null。
所以我的问题是:是否有可能从Gsoap使用安全的Metro服务,如果是这样,我做错了什么?我错过了什么?
谢谢!
答案 0 :(得分:0)
您是否尝试过在gSOAP Yahoo群组中提问?它在http://tech.groups.yahoo.com/group/gsoap/。没有承诺;我正在努力解决类似的问题(不同的服务,但是使用WSSE的gSOAP到Java Apache Axis),并且只得到了该组的一点帮助。
顺便说一下,有一个gSOAP补丁可以恢复完整的错误消息,而不是&#34;没有细节&#34;串。它在此消息中:http://tech.groups.yahoo.com/group/gsoap/message/19031