java - 在加密之前修改 CXF RequestSecurityToken 的 XML

标签 java web-services wcf cxf ws-security

我正在使用 Apache CXF 从 Java 客户端调用 WCF 服务。该服务在另一个地址使用 STS 进行保护。我已经将服务客户端配置为在调用主服务之前调用安全 token 并且它可以工作(它正在尝试调用 STS),但是 STS 期望在 RequestSecurityToken 中提供一些额外的数据。元素。 STS 的策略指定 RequestSecurityToken在发送之前进行加密和签名,这就是导致我出现问题的原因。加密和签名工作正常,但我似乎无法在加密之前修改 SOAP 消息。

我看了这个问题:How To Modify The Raw XML message of an Outbound CXF Request?虽然它有很大帮助,但我需要更改的 XML 部分驻留在 SOAP 消息的一部分中,该部分已加密并签名。

我做了一个 Interceptor并在我能找到的所有不同阶段进行了尝试,但似乎没有一个在 RequestSecurityToken 之间被调用正在创建并进行加密和签名。

有吗?或者已经可以向 RequestSecurityToken 添加额外元素的工具?

为清楚起见编辑:

这是我的 RST 现在的样子:

<wst:RequestSecurityToken xmlns:wst="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
    <wst:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue</wst:RequestType>
    <wsp:AppliesTo xmlns:wsp="http://www.w3.org/ns/ws-policy">
        <wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/08/addressing">
            <wsa:Address>http://localhost:9085/MyService</wsa:Address>
        </wsa:EndpointReference>
    </wsp:AppliesTo>
    <wst:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1</wst:TokenType>
    <wst:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/SymmetricKey</wst:KeyType>
    <wst:KeySize>192</wst:KeySize>
    <wst:Entropy>
        <wst:BinarySecret Type="http://docs.oasis-open.org/ws-sx/ws-trust/200512/Nonce">OlbfbuCUf3N2lNf9mhD03gfeMk0TfPI2nLWx8edlL5w=</wst:BinarySecret>
    </wst:Entropy>
    <wst:ComputedKeyAlgorithm>http://docs.oasis-open.org/ws-sx/ws-trust/200512/CK/PSHA1</wst:ComputedKeyAlgorithm>
    <wst:Renewing/>
</wst:RequestSecurityToken>

这是服务提供商的文档所说的大致内容(请注意末尾的 Credentials 元素):

<t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
    <t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
    <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
        <EndpointReference xmlns="http://www.w3.org/2005/08/addressing">
            <Address>http://localhost:9085/MyService</Address>
        </EndpointReference>
    </wsp:AppliesTo>
    <t:Entropy>
        <t:BinarySecret u:Id="uuid-e2d08122-45ab-45cd-80d1-46de2306836b-1" Type="http://schemas.xmlsoap.org/ws/2005/02/trust/Nonce" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">Ssex4V/175NCIOK1j4Mmbl47GiThOQMd</t:BinarySecret>
    </t:Entropy>
    <t:KeySize>192</t:KeySize>
    <t:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1</t:TokenType>
    <t:KeyType>http://schemas.xmlsoap.org/ws/2005/02/trust/SymmetricKey</t:KeyType>
    <Credentials>
        <UserName type="string">username</UserName>
        <Password type="string">password</Password>
    </Credentials>
    <t:ComputedKeyAlgorithm>http://schemas.xmlsoap.org/ws/2005/02/trust/CK/PSHA1</t:ComputedKeyAlgorithm>
</t:RequestSecurityToken>

这或多或少是我的代码——我应该在哪里更改 RST?:

  CXFBusFactory bf = new CXFBusFactory();
  Bus bus = bf.createBus();

  STSClient stsClient = new STSClient(bus);
  Map<String, Object> stsProperties = new HashMap<>();

  stsProperties.put(SecurityConstants.ENCRYPT_CRYPTO, stsMerlin);
  stsProperties.put(SecurityConstants.SIGNATURE_CRYPTO, stsMerlin);
  stsProperties.put(SecurityConstants.IS_BSP_COMPLIANT, "false");
  stsClient.setProperties(stsProperties);

  stsClient.setWsdlLocation("http://localhost:8090/SecurityTokenService?wsdl");
  stsClient.setServiceName("{http://tempuri.org/}Service");
  stsClient.setEndpointName("{http://tempuri.org/}Service_Port");

  stsClient.setKeySize(192);

  stsClient.getInInterceptors().add(new LoggingInInterceptor());
  stsClient.getOutInterceptors().add(new LoggingOutInterceptor());

  stsClient.setTokenType("http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1");
  stsClient.setSoap12();

  // Set the STS Client on the bus
  bus.setProperty(SecurityConstants.STS_CLIENT, stsClient);

  BusFactory.setDefaultBus(bus);
  BusFactory.setThreadDefaultBus(bus);

  MyService myService = new MyService();
  IMyService myServicePort = myService.getCustomBindingIMyService();

  Map<String, Object> ctx = ((BindingProvider)myServicePort).getRequestContext();
  ctx.put(SecurityConstants.ENCRYPT_CRYPTO, merlin);
  ctx.put(SecurityConstants.SIGNATURE_CRYPTO, merlin);
  ctx.put(SecurityConstants.IS_BSP_COMPLIANT, "false");

  myServicePort.doSomething();

任何见解表示赞赏。

最佳答案

所以我最终从 cxf 用户邮件列表获得了一些帮助。

响应如下:

What I would suggest you do here is to subclass the STSClient in CXF:

https://git-wip-us.apache.org/repos/asf?p=cxf.git;a=blob;f=rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java;h=afdaaeaa092460c5cbccd3f9723660ded9f12e2b;hb=HEAD

In particular, you want to override the "issue" method here:

https://git-wip-us.apache.org/repos/asf?p=cxf.git;a=blob;f=rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/AbstractSTSClient.java;h=4b4630e9d3fe0afab4496de0c7b0dd5df2fca292;hb=HEAD

Just copy the existing method code + add in your own custom code at the end.

果然,我对 STSClient 进行了子类化,并且能够复制-粘贴-覆盖 issue 方法,这使您可以访问 W3CDOMStreamWriter它包含 RequestSecurityToken,所以我可以通过在最终 writer 之前做更多的 writer.writeStartElement(...) 等来进行我想要的任何修改。 writeEndElement().

关于java - 在加密之前修改 CXF RequestSecurityToken 的 XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28286729/

相关文章:

java - java中的重定向

java - 在 Web 应用程序中创建 R 脚本并针对远程数据库执行它

android - 传回在单独线程中创建的变量?安卓

c# - 我可以为 ASP.NET SOAP Web 服务设置一个可选参数吗

c# - System.Net.Http.HttpClient 缓存行为

java - 为什么 HBase 中的 Bytes.toBytes() 无法返回我在我的情况下搜索的最后一行?

java - 当框架是Hybrid并且测试用例由Selenium中的excel驱动时,如何使用TestNG注释?

ruby-on-rails - 如何自定义 Rails 4 render() 查找文件的方式?

c# - wcf json 网络服务

ajax - "Baseaddress not found"- 在 GoDaddy 上部署 WCF 服务时出错