简体   繁体   中英

WSSE - Sign an element inside soapenv:Header

I want to add wsse:security to my soap message. This is my code:

    public Document signSoapMessage(SOAPMessage message) {
    try {
        Document doc = message.getSOAPBody().getOwnerDocument();
        Crypto crypto = CryptoFactory.getInstance(properties); //File

        WSSecHeader secHeader = new WSSecHeader(doc);
        secHeader.insertSecurityHeader();

        InputStream inStream = new FileInputStream(properties.getProperty("org.apache.ws.security.crypto.merlin.keystore.file"));

        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(inStream, properties.getProperty("privatekeypassword").toCharArray());

        String alias = ks.aliases().nextElement();
        X509Certificate cert = (X509Certificate) ks.getCertificate(alias);

        WSSecSignature sign = new WSSecSignature(secHeader);
        sign.setX509Certificate(cert);
        sign.setUserInfo(properties.getProperty("org.apache.ws.security.crypto.merlin.keystore.alias"), properties.getProperty("privatekeypassword"));
        sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE); // Binary Security Token - SecurityTokenReference
        sign.setUseSingleCertificate(true);
        sign.setDigestAlgo(DigestMethod.SHA1);

        //sign.build(crypto);
        Document signedDoc = sign.build(crypto);

        return signedDoc;
    } catch (SOAPException e) {
        e.printStackTrace();
        return null;
    } catch (WSSecurityException e) {
        e.printStackTrace();
        throw new RuntimeException("Error: " + e.getMessage());
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    } catch (CertificateException e) {
        e.printStackTrace();
        return null;
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
        return null;
    } catch (KeyStoreException e) {
        e.printStackTrace();
        return null;
    }
}

It works for soapenv:Body (It does add wsu:Id and xmlns:wsu parameters)

But there is an extra element in soapenv:Header and it doesn't sign this element. There is no wsu:Id and xmlns:wsu parameters and lack of one ds:Reference.

Example of not signed soap msg:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header>
    <!-- this element should be signed but is not - NOT WORKING -->
    <something>
    </something>

   </soapenv:Header>
   <!-- this element should be signed and It does. -->
   <soapenv:Body>
    </soapenv:Body>
</soapenv:Envelope>

I compare soap msg from my program to working soap msg from SoapUI project.

When I post a message to web service I get an error: wsse:InvalidSecurity - Soap Header must be signed . While in SoupUI it does works.

So my question is how can I force WSS4j to sign extra element inside soapenv:Header ?

Ok, I have solved the problem.

Normally this code should work in my situation.

//strange static method from apache o.O
org.apache.xml.security.Init.init();
List<WSEncryptionPart> wsEncryptionParts = new ArrayList<>();
WSEncryptionPart somethingPart = new WSEncryptionPart("something","somethingNamespace","");
wsEncryptionParts.add(somethingPart);
sign.addReferencesToSign(wsEncryptionParts);

Nevertheless, It doesn't work. It always throws an exception:

org.apache.wss4j.common.ext.WSSecurityException: No message with ID "noXMLSig" found in resource bundle "org/apache/xml/security/resource/xmlsecurity". Original Exception was a org.apache.wss4j.common.ext.WSSecurityException and message No message with ID "noEncElement" found in resource bundle "org/apache/xml/security/resource/xmlsecurity"

I could not find an answer to what is wrong with my soap message or code.

However, after a time of debugging of org.apache.wss4j.dom.message.WSSecSignature . I felt that something is wrong with the class. I decided to modify a method build(Crypto cr) .

public Document build(Crypto cr) throws WSSecurityException {
        LOG.debug("Beginning signing...");
        this.prepare(cr);
        if (this.getParts().isEmpty()) {
            this.getParts().add(WSSecurityUtil.getDefaultEncryptionPart(this.getDocument()));

            // --- Here is my edit - And it works!

            WSEncryptionPart aaa = new WSEncryptionPart("something","somethingNamespace","");
            this.getParts().add(aaa);

            // ----------------------------------

        } else {
            Iterator var2 = this.getParts().iterator();

            label33:
            while(true) {
                while(true) {
                    if (!var2.hasNext()) {
                        break label33;
                    }

                    WSEncryptionPart part = (WSEncryptionPart)var2.next();
                    if (part.getId() == null && "STRTransform".equals(part.getName())) {
                        part.setId(this.strUri);
                    } else if ("KeyInfo".equals(part.getName()) && "http://www.w3.org/2000/09/xmldsig#".equals(part.getNamespace()) && part.getElement() == null) {
                        Element keyInfoElement = this.getKeyInfoElement();
                        part.setElement(keyInfoElement);
                    }
                }
            }
        }

        List<javax.xml.crypto.dsig.Reference> referenceList = this.addReferencesToSign(this.getParts());
        this.computeSignature(referenceList);
        if (this.bstToken != null) {
            this.prependBSTElementToHeader();
        }

        return this.getDocument();
    }

Of course, the solution is quite weak. Yet, at least it works now.

The problem exists in the newest version:

wss4j-ws-security-dom 2.2.2

wss4j-ws-security-common 2.2.2

I guess it is supposed to work that way:

        WSSecSignature sign = new WSSecSignature(secHeader);
        sign.getParts().addAll(getEncryptionParts());

With getEncryptionParts() being the WSEncryptionPart List you want to add. If added that way, the build method is capable of finding them, without patching the framework.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM