目标:从第三方获取信息(使用Apache CXF)(因此无法控制或访问服务后端)Web服务 它使用WS-Trust,即在这种情况下使用安全令牌服务使用UsernameToken身份验证对用户进行身份验证。
我花了很长时间试图了解WS- *安全标准,同时尝试不同的框架和 工具(Axis,Apache CXF,带NetBeans的METRO,Microsoft .net,Eclipse的SoapUI插件等)连接到特定的服务 云端。我正在尝试开发一个从服务中获取信息的后端客户端。 Apache CXF在这里很有吸引力 因为它似乎是唯一一个不假设连接到Web服务的每个人都使用部署在Web应用程序服务器上的客户端的Java框架。
服务提供商提供了必要的证书和用户凭证,以便使用STS连接到服务。 他们还使用NetBeans和METRO提供了详细的用户指南,以创建部署在GlassFish服务器上的Web应用程序。 我已按照本指南操作并设法从Web服务获取数据。结论到目前为止:证书是有效的。
密钥库中存储了三个证书(包括链):
=============================================== ==================
NetBeans配置:
服务客户:
密钥库 - > token-signing-certificate.cer
Truststore - > web服务的加密-certificate.cer
STS客户:
Truststore - > token-encryption-certificate.cer
用户名 - >用户
密码 - > XXX
=============================================== ==================
大问题:如何在CXF中进行与NetBeans类似的配置?
我正在使用CXF版本:3.0.2
将此“翻译”为CXF给了我以下例外:
WARNING: Interceptor for {http://schemas.microsoft.com/ws/2008/06/identity/securitytokenservice}SecurityTokenService#{http://schemas.microsoft.com/ws/2008/06/identity/securitytokenservice}Trust13IssueAsync has thrown exception, unwinding now
org.apache.cxf.binding.soap.SoapFault: The signature or decryption was invalid
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.createSoapFault(WSS4JInInterceptor.java:841)
以下是我在CXF中尝试的内容(在许多其他内容中):
MyService service = new MyService(); // Stub created from WSDL (real service name has been renamed to MyService)
MyServiceInterface port = service.getPort();
org.apache.cxf.endpoint.Client client = ClientProxy.getClient(port);
Bus bus = ((EndpointImpl) client.getEndpoint()).getBus();
STSClient stsClient = new STSClient(bus);
stsClient.setWsdlLocation("https://login.some-domain.com/adfs/services/trust/mex"); // Web service is using ADFS 2.0 with MEX
stsClient.setServiceQName(new QName("http://schemas.microsoft.com/ws/2008/06/identity/securitytokenservice", "SecurityTokenService"));
stsClient.setEndpointQName(new QName("http://schemas.microsoft.com/ws/2008/06/identity/securitytokenservice", "UserNameWSTrustBinding_IWSTrust13Async"));
stsClient.setSendRenewing(false);
stsClient.getRequestContext().put("ws-security.sts.token.properties", "clientTruststore.properties");
stsClient.getRequestContext().put("ws-security.sts.token.username", "webservice-encryption"); // MOST LIKELY WRONG - WHERE DO I PUT THIS CERTIFICATE?
Map<String, Object> ctx = ((BindingProvider) port).getRequestContext();
ctx.put("ws-security.sts.prefer-wsmex", true); // If set to false some policies will not be satisfied
ctx.put("ws-security.username", "user"); // REQUIRED OR FAIL WITH: No username available
ctx.put("ws-security.password", "xxx"); // REQUIRED OR FAIL: No username available
ctx.put("ws-security.encryption.properties", "clientTruststore.properties"); // REQUIRED OR FAIL WITH: A encryption username needs to be declared
ctx.put("ws-security.encryption.username", "token-encryption"); // REQUIRED OR FAIL WITH: A encryption username needs to be declared
ctx.put("ws-security.signature.properties", "clientTruststore.properties");
ctx.put("ws-security.signature.username", "token-signing");
ctx.put("ws-security.is-bsp-compliant", "false");
ctx.put("ws-security.sts.client", stsClient);
port.callSomething(createMyRequestObject());
我试图根据以下链接(以及关于该主题的许多其他教程和文章)“解密”上面代码片段中使用的属性的含义,以便与WS-Trust和证书相关手。
http://cxf.apache.org/javadoc/latest/org/apache/cxf/ws/security/SecurityConstants.html
我已经尝试了使用常量的各种组合但没有成功。
如何将服务证书(webservice-encryption)“传递”到STS告诉它“这是我要使用的服务”?
顺便说一句,我使用Fiddler捕获了流量,与使用NetBeans解决方案捕获的流量相比,请求看起来完全正确,即它包含时间戳,加密部分等。
我保持“签名或解密无效”
有人可以帮忙吗?
答案 0 :(得分:0)
STS的响应方法是什么样的?这是一条错误消息还是看起来呼叫成功了?如果它是一条错误消息,那么看起来您可能正在使用错误的证书...您将需要启用服务登录以确定确切的错误是什么。如果调用成功,则在客户端启用DEBUG日志记录并查看问题所在。
科尔姆。
答案 1 :(得分:0)
我们遇到了类似的问题。也许您必须将JCE Unlimited Strength Policy jar文件添加到JDK?