Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java WSS4j元素在SOAP消息签名期间的顺序_Java_Web Services_Ws Security - Fatal编程技术网

Java WSS4j元素在SOAP消息签名期间的顺序

Java WSS4j元素在SOAP消息签名期间的顺序,java,web-services,ws-security,Java,Web Services,Ws Security,我正在用Java实现web服务客户端,它使用wss4j 1.6.8实现WS-Security(更准确地说,我需要签署SOAP消息)。服务器端要求请求具有以下结构: <Envelope> <Header> <wsse:Security mustUnderstand="1"> **<wsu:Timestamp wsu:Id="Timestamp-913ca68e-05ed-44e1-9d6c-b2f293da5

我正在用Java实现web服务客户端,它使用wss4j 1.6.8实现WS-Security(更准确地说,我需要签署SOAP消息)。服务器端要求请求具有以下结构:

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

**
2012-12-21T11:37:31Z
2012-12-21T11:42:31Z
**
MIID2jCCAsKg。。。
jdVY1HaDLusqO9UcxASE/GQHxyo=
L60mQelZERvXgLEgWlW50uJNqEA=
NmgACUqrYYc/Kp/F。。。
正文内容。。。
我的解决方案对文档(正文和时间戳元素)进行了签名,但出于某种原因,wss4j将时间戳元素放在该部分的底部,在
元素之后。请查看执行签名作业的来源:

 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);
    }
}
public static SOAPMessage signSoapMessage(SOAPMessage message、PrivateKey signingKey、X509Certificate signingCert、char[]passphrase)抛出WSSecurityException{
最终字符串别名=“signingKey”;
final int signatureValidityTime=3600;//1小时(秒)
WSSConfig config=新的WSSConfig();
config.setWsiBSPCompliant(false);
WSSecSignature builder=新的WSSecSignature(配置);
建造商。SETX509证书(签署证书);
setUserInfo(别名,新字符串(密码短语));
builder.setUseSingleCertificate(true);
setKeyIdentifierType(WSConstants.BST\u直接\u引用);
试一试{
Document Document=DanskeUtils.toDocument(消息);
WSSECCHEADER SECCHEADER=新的WSSECCHEADER();
secHeader.setMustUnderstand(true);
secHeader.insertSecurityHeader(文档);
WSSecTimestamp timestamp=新的WSSecTimestamp();
timestamp.setTimeToLive(signatureValidityTime);
document=timestamp.build(document,secHeader);
列表部件=新的ArrayList();
WSEncryptionPart timestampPart=新的WSEncryptionPart(“时间戳”,WSConstants.WSU_NS,”);
WSEncryptionPart bodyPart=新的WSEncryptionPart(WSConstants.ELEM_BODY,WSConstants.URI_SOAP11_ENV,“”);
零件。添加(零件);
零件。添加(车身零件);
建造商。设置零件(零件);
属性=新属性();
properties.setProperty(“org.apache.ws.security.crypto.provider”、“org.apache.ws.security.components.crypto.Merlin”);
Crypto Crypto=CryptoFactory.getInstance(属性);
KeyStore KeyStore=KeyStore.getInstance(“JKS”);
load(null,密码短语);
setKeyEntry(别名、签名密钥、密码短语、新证书[]{signingCert});
((Merlin)crypto).setKeyStore(keystore);
crypto.loadCertificate(新的ByteArrayInputStream(signingCert.getEncoded());
document=builder.build(document、crypto、secHeader);
返回Utils.updateSAP消息(文档、消息);
}捕获(例外e){
抛出新的WSSecurityException(WSSecurityException.Reason.SIGNING\u ISSUE,e);
}
}
在签署文件之前,您能帮我澄清一下如何更改元素的顺序吗?
谢谢大家!

WS-SEC规范说“当元素被添加到头块时,它们应该被添加到现有元素之前。”

因此,如果您首先添加时间戳,它将位于ws标头中任何现有子元素的上方。由于您是在添加timstamp之后对消息进行签名的,因此签名信息将再次预先添加到标头,因此它将显示在timestamp元素的上方


如果需要时间戳元素显示在最顶部,请将其添加到标题中,作为最终过程

构建签名后,您可以添加以下行:

timestamp.prependToHeader(secHeader);

它会将timestamp元素置于BinarySecurityToken元素之上。

谢谢。你的问题对我帮助很大。您能告诉我如何使用wss4j API验证soap消息的签名吗。