2012-12-27 67 views
6

我正在實現使用wss4j 1.6.8進行WS-Security(更精確地說我需要簽署SOAP消息)的Java Web服務客戶端。服務器端需要請求具有以下結構:在簽署SOAP消息期間WSS4j元素順序

<Envelope> 
    <Header> 
     <wsse:Security mustUnderstand="1"> 
      **<wsu:Timestamp wsu:Id="Timestamp-913ca68e-05ed-44e1-9d6c-b2f293da5a1d"> 
       <wsu:Created>2012-12-21T11:37:31Z</wsu:Created> 
       <wsu:Expires>2012-12-21T11:42:31Z</wsu:Expires> 
      </wsu:Timestamp>** 
      <wsse:BinarySecurityToken> 
       MIID2jCCAsKg... 
      </wsse:BinarySecurityToken> 
      <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> 
       <SignedInfo> 
        <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> 
        <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> 
        <Reference URI="#Timestamp-913ca68e-05ed-44e1-9d6c-b2f293da5a1d"> 
         <Transforms> 
          <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> 
         </Transforms> 
         <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> 
         <DigestValue>jdVY1HaDLusqO9UcxASE/GQHxyo=</DigestValue> 
        </Reference> 
        <Reference URI="#Body-e344eef1-2d8a-42d0-8a30-361ee61a8617"> 
         <Transforms> 
          <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> 
         </Transforms> 
         <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> 
         <DigestValue>L60mQelZERvXgLEgWlW50uJNqEA=</DigestValue> 
        </Reference> 
       </SignedInfo> 
       <SignatureValue> 
        NmgACUqrYYc/Kp/F... 
       </SignatureValue> 
       <KeyInfo> 
        <wsse:SecurityTokenReference xmlns=""> 
         <wsse:Reference URI="#SecurityToken-3f054298-711c-4090-95c3-105e1093f3ba" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/> 
        </wsse:SecurityTokenReference> 
       </KeyInfo> 
      </Signature> 
     </wsse:Security> 
    </S:Header> 
    <S:Body> 
     Body content... 
    </S:Body> 
</Envelope> 

我的解決方案簽署文件(包括身體和時間戳元素),但由於某些原因WSS4J把時間戳元素到部分的底部,之後<wsse:BinarySecurityToken><Signature>元素是什麼是錯的。請看簽署工作的來源:

public static SOAPMessage signSoapMessage(SOAPMessage message, PrivateKey signingKey, X509Certificate signingCert, char[] passphrase) throws WSSecurityException { 

    final String alias = "signingKey"; 
    final int signatureValidityTime = 3600; // 1hour in seconds 

    WSSConfig config = new WSSConfig(); 
    config.setWsiBSPCompliant(false); 

    WSSecSignature builder = new WSSecSignature(config); 

    builder.setX509Certificate(signingCert); 
    builder.setUserInfo(alias, new String(passphrase)); 
    builder.setUseSingleCertificate(true); 
    builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE); 

    try { 
     Document document = DanskeUtils.toDocument(message); 
     WSSecHeader secHeader = new WSSecHeader(); 
     secHeader.setMustUnderstand(true); 
     secHeader.insertSecurityHeader(document); 

     WSSecTimestamp timestamp = new WSSecTimestamp(); 
     timestamp.setTimeToLive(signatureValidityTime); 
     document = timestamp.build(document, secHeader); 

     List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>(); 
     WSEncryptionPart timestampPart = new WSEncryptionPart("Timestamp", WSConstants.WSU_NS, ""); 
     WSEncryptionPart bodyPart = new WSEncryptionPart(WSConstants.ELEM_BODY, WSConstants.URI_SOAP11_ENV, ""); 
     parts.add(timestampPart); 
     parts.add(bodyPart); 
     builder.setParts(parts); 

     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 keystore = KeyStore.getInstance("JKS"); 
     keystore.load(null, passphrase); 
     keystore.setKeyEntry(alias, signingKey, passphrase, new Certificate[]{signingCert}); 
     ((Merlin) crypto).setKeyStore(keystore); 
     crypto.loadCertificate(new ByteArrayInputStream(signingCert.getEncoded())); 

     document = builder.build(document, crypto, secHeader); 
     return Utils.updateSoapMessage(document, message); 
    } catch (Exception e) { 
     throw new WSSecurityException(WSSecurityException.Reason.SIGNING_ISSUE, e); 
    } 
} 

請你幫我解釋一下,如何在文檔簽名前改變元素的順序? 謝謝!

+0

謝謝。你的問題幫了我很多。您能否讓我知道如何使用wss4j apis驗證soap消息的簽名。 –

回答

1

WS-SEC規範說:「當元素被添加到標題塊時,它們應該被添加到現有的元素中。」

因此,如果您首先添加時間戳,它將位於ws頭中任何現有的子元素之上。由於您在添加timstamp後正在對消息進行簽名,因此簽名信息將再次預先添加到頭部,因此它將出現在時間戳記元素上方。

如果需要時間戳元素出現在最高層,將其添加到標題作爲最終處理

0

後您打造的簽名可以加入這一行:

timestamp.prependToHeader(secHeader); 

它會將時間戳元素放在BinarySecurityToken元素的上方。