繁体   English   中英

WSSE - 在 soapenv:Header 中签署一个元素

[英]WSSE - Sign an element inside soapenv:Header

我想将wsse:security添加到我的肥皂消息中。 这是我的代码:

    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;
    }
}

它适用于soapenv:Body (它确实添加了wsu:Idxmlns:wsu参数)

但是在soapenv:Header 中有一个额外的元素,它没有对这个元素进行签名。 没有wsu:Idxmlns:wsu参数并且缺少一个 ds:Reference。

未签名的肥皂味的示例:

<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>

我将程序中的肥皂味精与 SoapUI 项目中的肥皂味精进行了比较。

当我向 Web 服务发布消息时,出现错误: wsse:InvalidSecurity - Soap Header must be signed 在 SoupUI 中它确实有效。

所以我的问题是如何强制WSS4jsoapenv:Header 中签署额外的元素?

好的,我已经解决了这个问题。

通常这段代码应该适用于我的情况。

//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);

尽管如此,它不起作用。 它总是抛出异常:

org.apache.wss4j.common.ext.WSSecurityException:在资源包“org/apache/xml/security/resource/xmlsecurity”中找不到 ID 为“noXMLSig”的消息。 原始异常是 org.apache.wss4j.common.ext.WSSecurityException 和消息 No message with ID "noEncElement" found in resource bundle "org/apache/xml/security/resource/xmlsecurity"

我找不到我的肥皂消息或代码出了什么问题的答案。

但是,经过一段时间的org.apache.wss4j.dom.message.WSSecSignature调试。 我觉得班级有问题。 我决定修改一个方法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();
    }

当然,该解决方案非常薄弱。 然而,至少它现在有效。

最新版本存在问题:

wss4j-ws-security-dom 2.2.2

wss4j-ws-security-common 2.2.2

我想它应该这样工作:

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

getEncryptionParts() 是您要添加的 WSEncryptionPart 列表。 如果以这种方式添加,则 build 方法能够找到它们,而无需修补框架。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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