如何使用 wss4j 库验证 soap 签名

How to validate soap signature using wss4j library

我有一条肥皂消息如下

<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
   <env: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" env:mustUnderstand="1">
         <wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="X509-3FE116EADE4A5ACE1C14636491396431">MIIEwjCCBCugAwIBAgIEUZF6sjANBgkqhkiG9w0BAQUFADCBmDEZMBcGA1UEChMQR3J1cG8gVGuYSBTPLrZBFdug27AhMqAzvjmp8G4Aj65E0QKDrnFIU4KTMyhSIFRzL5fATWsohdLXqcebHf+XmlNSQ==</wsse:BinarySecurityToken>
         <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-3FE116EADE4A5ACE1C14636491396595">
            <ds:SignedInfo>
               <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
               <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
               <ds:Reference URI="#id-3FE116EADE4A5ACE1C14636491396564">
                  <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>hsrhNdt06tOUYlbV4gmkEwZEpXg=</ds:DigestValue>
               </ds:Reference>
            </ds:SignedInfo>
            <ds:SignatureValue>rtBv9+NmGZ58HN1XaWXZDQs2DpoiRCONt3XTM6N/R4SyrVK8ltbZebl0WnBQ==</ds:SignatureValue>
            <ds:KeyInfo Id="KI-3FE116EADE4A5ACE1C14636491396452">
               <wsse:SecurityTokenReference wsu:Id="STR-3FE116EADE4A5ACE1C14636491396483">
                  <wsse:Reference URI="#X509-3FE116EADE4A5ACE1C14636491396431" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" />
               </wsse:SecurityTokenReference>
            </ds:KeyInfo>
         </ds:Signature>
      </wsse:Security>
      <add:MessageID xmlns:add="http://schemas.xmlsoap.org/ws/2004/08/addressing">urn:uuid:b43ab47f-8ecb-4ac4-8b36-ee3649a734bf</add:MessageID>
   </env:Header>
   <env:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-3FE116EADE4A5ACE1C14636491396564">
      <request>
         <param1>234</param1>
         <param2>sdf2342</param2>
      </request>
   </env:Body>
</env:Envelope>

如何使用 wss4j 验证消息签名?我想在 java 程序中执行此操作,而不是在 axiscxf.

等任何框架中执行此操作

签名与消息不对应会抛出WsSecurityException

public void processSoapSecurityHeader(String soapRequest, String keyStore, String keyStorePwd, String alias) throws Exception {

    SOAPMessage soapMessage = MessageFactory.newInstance().createMessage(null, new  ByteArrayInputStream(soapRequest.getBytes()));
    FileInputStream is = new FileInputStream(keyStore);
    KeyPair keypair = null;
    KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
    keystore.load(is, keyStorePwd.toCharArray());
    Certificate cert = null;
    Key key = keystore.getKey(alias, keyStorePwd.toCharArray());
    if (key instanceof PrivateKey) {
      cert = keystore.getCertificate(alias);
      PublicKey publicKey = cert.getPublicKey();
      keypair = new KeyPair(publicKey, (PrivateKey) key);
    }
     Properties properties = new Properties();
     properties.setProperty("org.apache.ws.security.crypto.provider", "org.apache.ws.security.components.crypto.Merlin");
     Crypto crypto = CryptoFactory.getInstance(properties);
     keystore.setKeyEntry(alias, keypair.getPrivate(), keyStorePwd.toCharArray(), new Certificate[]{cert});
     ((Merlin) crypto).setKeyStore(keystore);
     crypto.loadCertificate(new ByteArrayInputStream(cert.getEncoded()));
     WSSecurityEngine engine = new WSSecurityEngine();
     WSSConfig config = WSSConfig.getNewInstance();
     config.setWsiBSPCompliant(false);
     engine.setWssConfig(config);
     List<WSSecurityEngineResult> res = engine.processSecurityHeader(toDocument(soapMessage), null, null, crypto);
     for (WSSecurityEngineResult ers : res) {
           LOG.trace("Details of security header after validation {}" , ers.toString());
     }
     LOG.debug("Validation code executed");
}