【问题标题】:Soap request signed by certificate. WS-Security由证书签名的肥皂请求。 WS-安全
【发布时间】:2019-12-07 08:56:17
【问题描述】:

我收到了包含安全策略的 WSDL,就目前而言,从 wsdl 来看,我发现这意味着我需要它来使用证书进行签名。不应使用令牌服务器。

我做了什么: 我使用 cxf wsdl2java 从 wsdl 文件创建 java 类。到目前为止,我看到 CXF 可以很好地自动处理所有签名,所以我在 java 端 STSClient 上添加了客户端上的 ws-security.signature.crypto 和 ws-security.encryption.crypto。基本上什么都不做,我的肥皂请求只包含没有任何签名数据的正文。结果什么也没发生,也没有打印出错误,这让我的问题很难解决。

问题: 如何在没有任何用户名/密码的情况下签署没有令牌服务器的肥皂请求? 提供的wsdl中的地址也是http,我应该将其覆盖为https吗?

收到 wsdl Policy sn-p:

 <wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
              xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
              wsu:Id="SigOnly">
    <wsp:ExactlyOne>
      <wsp:All>
        <sp:AsymmetricBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
          <wsp:Policy>
            <sp:InitiatorToken>
              <wsp:Policy>
                <sp:X509Token
                        sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Always">
                  <wsp:Policy>
                    <sp:WssX509V3Token10/>
                  </wsp:Policy>
                </sp:X509Token>
              </wsp:Policy>
            </sp:InitiatorToken>
            <sp:RecipientToken>
              <wsp:Policy>
                <sp:X509Token
                        sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Always">
                  <wsp:Policy>
                    <sp:WssX509V3Token10/>
                  </wsp:Policy>
                </sp:X509Token>
              </wsp:Policy>
            </sp:RecipientToken>
            <sp:AlgorithmSuite>
              <wsp:Policy>
                <sp:TripleDesRsa15/>
              </wsp:Policy>
            </sp:AlgorithmSuite>
            <sp:Layout>
              <wsp:Policy>
                <sp:Strict/>
              </wsp:Policy>
            </sp:Layout>
            <sp:IncludeTimestamp/>
            <sp:OnlySignEntireHeadersAndBody/>
          </wsp:Policy>
        </sp:AsymmetricBinding>
        <sp:Wss10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
          <wsp:Policy>
            <sp:MustSupportRefKeyIdentifier/>
            <sp:MustSupportRefIssuerSerial/>
          </wsp:Policy>
        </sp:Wss10>
        <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
          <sp:Body/>
        </sp:SignedParts>
      </wsp:All>
    </wsp:ExactlyOne>
  </wsp:Policy>

收到的消息头示例:

  <soap:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
                   xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
                   soap:mustUnderstand="1">
      <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-****">
        <ds:SignedInfo>
          <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
            <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="soap"/>
          </ds:CanonicalizationMethod>
          <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
          <ds:Reference URI="#id-***">
            <ds:Transforms>
              <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <ds:DigestValue>value=</ds:DigestValue>
          </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>
          signatureValue==
        </ds:SignatureValue>
        <ds:KeyInfo Id="KI-***">
          <wsse:SecurityTokenReference wsu:Id="STR-***">
            <ds:X509Data>
              <ds:X509IssuerSerial>
                <ds:X509IssuerName>issuer name
                </ds:X509IssuerName>
                <ds:X509SerialNumber>nmber</ds:X509SerialNumber>
              </ds:X509IssuerSerial>
            </ds:X509Data>
          </wsse:SecurityTokenReference>
        </ds:KeyInfo>
      </ds:Signature>
    </wsse:Security>
  </soap:Header>

我的 java sn-p:

    Client client = ClientProxy.getClient(generatedService);

    Init.init();
    Properties properties = new Properties();
    properties.setProperty("org.apache.ws.security.crypto.provider", "org.apache.ws.security.components.crypto.Merlin");
    properties.setProperty("org.apache.ws.security.crypto.merlin.keystore.type", "jks");
    properties.setProperty("org.apache.ws.security.crypto.merlin.keystore.password", keystorePassword);
    properties.setProperty("org.apache.ws.security.crypto.merlin.keystore.alias", signedCertificateAliasInTheKeystore);
    properties.setProperty("org.apache.ws.security.crypto.merlin.file", new ClassPathResource(keyStore).getPath());
    properties.setProperty("org.apache.ws.security.crypto.merlin.keystore.private.password", keystorePassword);

    Merlin crypto = null;
    try {
      crypto = (Merlin) CryptoFactory.getInstance(properties);
    }
    catch (WSSecurityException e) {
      e.printStackTrace();//temp
    }

    STSClient stsClient = new STSClient(((EndpointImpl) client.getEndpoint()).getBus());
    Map<String, Object> stsClientProperties = new HashMap<>();
    stsClient.setWsdlLocation(new ClassPathResource("MyWsdl.wsdl").getPath());
    stsClientProperties.put("ws-security.signature.crypto", crypto);
    stsClientProperties.put("ws-security.encryption.crypto", crypto);
    stsClient.setProperties(stsClientProperties);

    BindingProvider bindingProvider = (BindingProvider) generatedService;
    bindingProvider.getRequestContext().put("ws-security.sts.client", stsClient);
    generatedService.callToTheOuterWorld(data);


第二次尝试,基本上是复制 link:

org.apache.cxf.endpoint.Client client = ClientProxy.getClient(generatedService);
org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();
Map<String,Object> outProps = new HashMap<String,Object>();
outProps.put(WSHandlerConstants.USER, "keystoreAlias");
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS,
        ClientPasswordCallback.class.getName()); //callback has keystore password
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPT);
outProps.put(WSHandlerConstants.SIG_PROP_FILE, new ClassPathResource("client_sign.properties").getPath());
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
cxfEndpoint.getOutInterceptors().add(wssOut);
generatedService.callToTheOuterWorld(data)

引发:由 org.apache.wss4j.common.ext.WSSecurityException: EncryptionCrypto 实例化失败引起 如果我删除 WSHandlerConstants.ENCRYPT 我没有异常但请求中仍然缺少标头。

【问题讨论】:

    标签: java spring-boot soap-client wsdl2java cxf-client


    【解决方案1】:

    我解决了自己的问题。 基本上我在 SO 示例中找到了如何打印出我的请求数据,我用它来查看我的请求,结果它将标头覆盖为 null :) 记下“getHeaders()”方法。

    Binding binding = bindingProvider.getBinding();
    List<Handler> handlerChain = binding.getHandlerChain();
    andlerChain.add(new SOAPLoggingHandler());
    binding.setHandlerChain(handlerChain);
    
      class SOAPLoggingHandler implements SOAPHandler<SOAPMessageContext> {
        public Set<QName> getHeaders() {
          return null;
        }
    
        public boolean handleMessage(SOAPMessageContext smc) {
          logToSystemOut(smc);
          return true;
        }
    
        public boolean handleFault(SOAPMessageContext smc) {
          logToSystemOut(smc);
          return true;
        }
    
        public void close(MessageContext messageContext) {
        }
    
        private void logToSystemOut(SOAPMessageContext smc) {
          Boolean outboundProperty = (Boolean)
                  smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
    
          if (outboundProperty.booleanValue()) {
            System.out.println("\nOutbound message:");
          }
          else {
            System.out.println("\nInbound message:");
          }
    
          SOAPMessage message = smc.getMessage();
          try {
            message.writeTo(System.out);
            System.out.println("");
          }
          catch (Exception e) {
            System.out.println("Exception in handler: " + e);
          }
        }
      }
    

    【讨论】:

    • 如果您在 wsdl 中没有安全策略但需要添加 BinarySecurityToken、Signature 和 Digest 怎么办?我还使用 cxf 3.4 中的 wsdl2java 创建了客户端,我需要添加标头
    • 嗨@AlejandroL。你找到解决方案了吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-08
    • 1970-01-01
    • 1970-01-01
    • 2011-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多