【发布时间】:2015-01-26 11:59:00
【问题描述】:
目标:从第三方获取信息(使用 Apache CXF)(因此无法控制或访问服务后端)Web 服务 它使用 WS-Trust,即它使用安全令牌服务对用户进行身份验证,在这种情况下使用 UsernameToken 身份验证。
我花了很长时间尝试了解 WS-* 安全标准,同时尝试不同的框架和 工具(Axis、Apache CXF、METRO with NetBeans、Microsoft .net、用于 Eclipse 的 SoapUI 插件等)连接到特定服务 云端。我正在尝试开发一个从服务中获取信息的后端客户端。 Apache CXF 在这里很有吸引力 因为它似乎是唯一一个不假定每个连接到 Web 服务的人都使用部署在 Web 应用程序服务器上的客户端的 Java 框架。
服务提供商已提供必要的证书和用户凭据以使用 STS 连接到服务。 他们还提供了使用 NetBeans 和 METRO 创建部署在 GlassFish 服务器上的 Web 应用程序的详细用户指南。 我已遵循本指南并设法从 Web 服务获取数据。到目前为止的结论:证书是有效的。
一个密钥库(包括链)中存储了三个证书:
- webservice-encryption-certificate.cer(密钥库别名:webservice-encryption)
- token-signing-certificate.cer(密钥库别名: 令牌签名)
- token-encryption-certificate.cer(密钥库别名:token-encryption)
================================================ ==================
NetBeans 配置:
服务客户端:
密钥库 -> 令牌签名证书.cer
信任库 -> webservice-encryption-certificate.cer
STS 客户端:
信任库 -> 令牌加密证书.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());
我已尝试根据以下链接(以及有关该主题的许多其他教程和文章)“解密”上面代码 sn-p 中使用的属性的含义,以使其与 WS-Trust 和证书在手。
http://cxf.apache.org/javadoc/latest/org/apache/cxf/ws/security/SecurityConstants.html
我已经尝试了使用常量的各种组合,但没有成功。
如何将服务证书(webservice-encryption)“传递”给 STS,告诉它“这是我要使用的服务”?
顺便说一句,我使用 Fiddler 捕获了流量,与使用 NetBeans 解决方案捕获的流量相比,请求看起来完全正确,即它包含时间戳、加密部分等。
我不断收到“签名或解密无效”
有人可以帮忙吗?
【问题讨论】:
-
您好,您找到解决方案了吗?我遇到了类似的问题,我无法让它工作。谢谢!