gpt4 book ai didi

soap - 在 Apache JMeter 的 SOAP 请求中添加签名

转载 作者:行者123 更新时间:2023-12-05 00:57:19 25 4
gpt4 key购买 nike

我需要在 Apache JMeter 的 SOAP 请求中使用 X509 证书添加签名。
我已经有了 .p12。
请帮助我如何在 Apache JMeter 中实现它。
我知道如何在 SOAPUI 中做到这一点,但在 JMeter 中找不到任何方法。

最佳答案

不知道你是否还需要这个答案,但我遇到了同样的问题,并在几天的工作后得到了解决,我想其他人也可能会觉得这很有用......

我的回答基于 Dmitri T 的回答; the blog post on blazemeter , this bugreport + 一些自定义黑客攻击。

假设您需要签署此请求:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ser="http://custom.namespace.com/service-v1.0-rc2">
<soap:Header>
<wsa:MessageID xmlns:wsa="http://www.w3.org/2004/12/addressing">a2749a0f-555-9135-367ed901d244</wsa:MessageID>
</soap:Header>
<soap:Body>
<ser:request>
<ser:person>
<ser:id>11552</ser:id>
<ser:number>81067776992</ser:number>
</ser:person>
</ser:request>
</soap:Body>
</soap:Envelope>

您已按照 blazemeter 指南进行操作,直到使用自定义 java 代码签署请求的部分。

不要使用该代码,请执行以下操作:

将以下代码复制粘贴到 JMeter(3.0) 中:
import com.example.wss.SOAPSecurity;
import org.apache.jmeter.services.FileServer;

// get SOAP message from parent sampler body
String soapData = sampler.getArguments().getArgument(0).getValue();

String baseDir = FileServer.getFileServer().getBaseDir();

String pathToKeystore = baseDir + File.separator + "keystore_files" + File.separator + "your.jks";
String keystorePassword = "yourPassword";
int timeToLive = 5000;
String signingAlias = "yourAlias";
String encryptAlias = "yourEncryptingAlias";
String secureSoap = "";

try {
secureSoap = SOAPSecurity.secureSoapMessageFromString(soapData, pathToKeystore, keystorePassword, null, null, timeToLive, signingAlias, yourEncryptingAlias);
}
catch (Exception ex){
log.warn("Error in script", ex);
throw ex;
}

// replace parent sampler body with secured SOAP message
sampler.getArguments().getArgument(0).setValue(secureSoap);
vars.put("SoapDataRaw", secureSoap);

使用 groovy 作为解释器。

这是适用于我的用例的 java 类文件:
package com.example.wss;

import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSEncryptionPart;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.CryptoFactory;
import org.apache.ws.security.components.crypto.Merlin;
import org.apache.ws.security.message.WSSecEncrypt;
import org.apache.ws.security.message.WSSecHeader;
import org.apache.ws.security.message.WSSecSignature;
import org.apache.ws.security.message.WSSecTimestamp;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.soap.*;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;

import javax.net.ssl.*;
import javax.xml.transform.dom.DOMSource;
import java.io.*;
import java.security.*;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class SOAPSecurity {

private KeyStore keystore;
private KeyManagerFactory keyManagerFactory;
private String keystorePassword;

private TrustManagerFactory trustManagerFactory;
private KeyStore truststore;
private String truststorePassword;

private Crypto crypto;

public SOAPSecurity(String pathToKeystore, String keystorePassword, String pathToTruststore, String truststorePassword) throws IOException, NoSuchAlgorithmException, KeyStoreException, CertificateException, UnrecoverableKeyException, KeyManagementException, WSSecurityException {

keystore = KeyStore.getInstance("JKS");
InputStream fileReader = new FileInputStream(new File(pathToKeystore));
keystore.load(fileReader, keystorePassword.toCharArray());
this.keystorePassword = keystorePassword;

keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keystore, keystorePassword.toCharArray());

Properties properties = new Properties();
properties.setProperty("org.apache.ws.security.crypto.provider", "org.apache.ws.security.components.crypto.Merlin");
crypto = CryptoFactory.getInstance(properties);
((Merlin) crypto).setKeyStore(keystore);

truststore = KeyStore.getInstance("JKS");
fileReader = new FileInputStream(new File(pathToTruststore));
truststore.load(fileReader, truststorePassword.toCharArray());
this.truststorePassword = truststorePassword;

trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
trustManagerFactory.init(truststore);
}

//EDITOR: added constructor without truststore
public SOAPSecurity(String pathToKeystore, String keystorePassword) throws IOException, NoSuchAlgorithmException, KeyStoreException, CertificateException, UnrecoverableKeyException, KeyManagementException, WSSecurityException {

keystore = KeyStore.getInstance("JKS");
InputStream fileReader = new FileInputStream(new File(pathToKeystore));
keystore.load(fileReader, keystorePassword.toCharArray());
this.keystorePassword = keystorePassword;

keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keystore, keystorePassword.toCharArray());

Properties properties = new Properties();
properties.setProperty("org.apache.ws.security.crypto.provider", "org.apache.ws.security.components.crypto.Merlin");
crypto = CryptoFactory.getInstance(properties);
((Merlin) crypto).setKeyStore(keystore);
}

public static String secureSoapMessageFromFile(String messagePath, String pathToKeystore, String keystorePassword,
String pathToTruststore, String trustStorePassword, int timeToLive,
String signingAlias, String encryptAlias) throws
SAXException, ParserConfigurationException, SOAPException, IOException, WSSecurityException,
TransformerException, UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException,
KeyStoreException, KeyManagementException {

SOAPSecurity soapSecurity = new SOAPSecurity(pathToKeystore, keystorePassword, pathToTruststore, trustStorePassword);
SOAPMessage soapMessage = SOAPSecurity.createSOAPRequestFromFile(messagePath);
return soapSecurity.applyWSSecurity(soapMessage, timeToLive, signingAlias, encryptAlias);
}

public static String secureSoapMessageFromString(String messageString, String pathToKeystore, String keystorePassword,
String pathToTruststore, String trustStorePassword, int timeToLive,
String signingAlias, String encryptAlias) throws
SAXException, ParserConfigurationException, SOAPException, IOException, WSSecurityException,
TransformerException, UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException,
KeyStoreException, KeyManagementException {

SOAPSecurity soapSecurity = new SOAPSecurity(pathToKeystore, keystorePassword);
SOAPMessage soapMessage = SOAPSecurity.createSOAPRequestFromString(messageString);
return soapSecurity.applyWSSecurity(soapMessage, timeToLive, signingAlias, encryptAlias);
}

//EDITOR: ...and static signing methods as well
public static String secureSoapMessageFromString(String messageString, String pathToKeystore, String keystorePassword,
int timeToLive,
String signingAlias, String encryptAlias) throws
SAXException, ParserConfigurationException, SOAPException, IOException, WSSecurityException,
TransformerException, UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException,
KeyStoreException, KeyManagementException {

SOAPSecurity soapSecurity = new SOAPSecurity(pathToKeystore, keystorePassword);
SOAPMessage soapMessage = SOAPSecurity.createSOAPRequestFromString(messageString);
return soapSecurity.applyWSSecurity(soapMessage, timeToLive, signingAlias, encryptAlias);
}

public static String secureSoapMessageFromFile(String messagePath, String pathToKeystore, String keystorePassword,
int timeToLive,
String signingAlias, String encryptAlias) throws
SAXException, ParserConfigurationException, SOAPException, IOException, WSSecurityException,
TransformerException, UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException,
KeyStoreException, KeyManagementException {

SOAPSecurity soapSecurity = new SOAPSecurity(pathToKeystore, keystorePassword);
SOAPMessage soapMessage = SOAPSecurity.createSOAPRequestFromFile(messagePath);
return soapSecurity.applyWSSecurity(soapMessage, timeToLive, signingAlias, encryptAlias);
}

public interface SOAPDocWriter {
Document writeDocument(String s, DocumentBuilder documentBuilder) throws IOException, SAXException;
}

public static SOAPMessage createSOAPRequestFromFile(String messagePath) throws SOAPException, IOException, ParserConfigurationException, SAXException {

SOAPDocWriter pathWriter = (s, d) -> {
File messageFile = new File(s);
return d.parse(new InputSource(new FileInputStream(messageFile)));
};

return createSOAPRequestLambda(messagePath, pathWriter);
}

public static SOAPMessage createSOAPRequestFromString(String messageString) throws SOAPException, IOException, ParserConfigurationException, SAXException {

SOAPDocWriter stringWriter = (s, d) -> d.parse(new InputSource(new StringReader(s)));
return createSOAPRequestLambda(messageString, stringWriter);
}

private static SOAPMessage createSOAPRequestLambda(String s, SOAPDocWriter w) throws SOAPException, IOException, ParserConfigurationException, SAXException
{
//MessageFactory messageFactory = MessageFactory.newInstance();
//we use the SOAP 1.2 specification
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();

SOAPEnvelope soapEnvelope = soapPart.getEnvelope();

SOAPBody soapBody = soapEnvelope.getBody();

DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = w.writeDocument(s, documentBuilder);

soapBody.addDocument(document);

soapMessage.saveChanges();

return soapMessage;
}

public static Document toDocument(SOAPMessage soapMsg) throws TransformerConfigurationException, TransformerException, SOAPException, IOException {
Source src = soapMsg.getSOAPPart().getContent();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMResult result = new DOMResult();
transformer.transform(src, result);
return (Document) result.getNode();
}

/**
* Secures a soap message according to the given security actions
*
* @param soapMessage the soap message to be secured
* @param timestampTimeToLive optional: the time to live for the timestamp
* @param signatureKeyAlias optional: the alias for the signature key in the keystore
* @param encryptionKeyAlias optional: the alias for the encryption key in the keystore
* @throws WSSecurityException
* @throws IOException
* @throws SOAPException
* @throws TransformerException
*/
public String applyWSSecurity(SOAPMessage soapMessage,
int timestampTimeToLive,
String signatureKeyAlias,
String encryptionKeyAlias) throws WSSecurityException, IOException, SOAPException, TransformerException {

Document soapMessageDocument = toDocument(soapMessage);

// add security header
WSSecHeader securityHeader = new WSSecHeader();
securityHeader.setMustUnderstand(false);

//we keep the security header element because we need it afterwards

Element secHead = securityHeader.insertSecurityHeader(soapMessageDocument);

/*
for a reason not yet clear to me this method of signing creates a soap request inside a soap request
I don't know why but I know how to work around it:
*/

//append the security header to the soap:Header parent
soapMessageDocument.getElementsByTagName("soap:Header").item(0).appendChild(secHead);

//move the soap:Envelope inner soap message to the root of the document and omit the env:Envelope tree
soapMessageDocument.replaceChild(soapMessageDocument.getElementsByTagName("soap:Envelope").item(0),
soapMessageDocument.getElementsByTagName("env:Envelope").item(0));

//for debugging purposes -> this output shows up in the console output of JMeter.bat
//System.out.println("insert:"+soapMessageDocument.getFirstChild().getNodeName()+",soap:"+soapMessageDocument.getElementsByTagName("soap:Envelope").item(0).getNodeName());

WSSecTimestamp timestamp = null;

// timestamp document
timestamp = new WSSecTimestamp();
timestamp.setTimeToLive(timestampTimeToLive);
timestamp.build(soapMessageDocument, securityHeader);

// sign document

/*
EDITOR: originals are commented out and replaced by own values
values should be adapted from SOAPUI and searched for at:
https://ws.apache.org/wss4j/apidocs/org/apache/wss4j/dom/WSConstants.html
*/

WSSecSignature signatureBuilder = new WSSecSignature();
signatureBuilder.setUserInfo(signatureKeyAlias, keystorePassword);
signatureBuilder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
//signatureBuilder.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
signatureBuilder.setSignatureAlgorithm("http://www.w3.org/2000/09/xmldsig#rsa-sha1");
signatureBuilder.setSigCanonicalization(WSConstants.C14N_EXCL_OMIT_COMMENTS);
/*
also setDigestAlgo can be set
https://ws.apache.org/wss4j/apidocs/org/apache/wss4j/dom/message/WSSecSignature.html#setDigestAlgo-java.lang.String-
but I used the default so I didn't bother
*/

//also custom
signatureBuilder.setUseSingleCertificate(true);

List<WSEncryptionPart> signatureParts = new ArrayList<WSEncryptionPart>();

//WSEncryptionPart timestampPart = new WSEncryptionPart(timestamp.getId());
WSEncryptionPart timestampPart = new WSEncryptionPart("Timestamp","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd","Content");
signatureParts.add(timestampPart);

//WSEncryptionPart bodyPart = new WSEncryptionPart(WSConstants.ELEM_BODY, WSConstants.URI_SOAP11_ENV, "Element");
WSEncryptionPart bodyPart = new WSEncryptionPart("Body","http://www.w3.org/2003/05/soap-envelope", "Content");
signatureParts.add(bodyPart);
signatureBuilder.setParts(signatureParts);

signatureBuilder.build(soapMessageDocument, crypto, securityHeader);

// encrypt document
/*
we didn't encrypt so no need for this code

(encryption code untested (by me))

WSSecEncrypt encrypt = new WSSecEncrypt();
encrypt.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
encrypt.setSymmetricEncAlgorithm(WSConstants.AES_128_GCM);
encrypt.setKeyEncAlgo(WSConstants.KEYTRANSPORT_RSAOEP);
encrypt.setUserInfo(encryptionKeyAlias, keystorePassword);

List<WSEncryptionPart> encryptionParts = new ArrayList<WSEncryptionPart>();
WSEncryptionPart encryptionSignaturePart = new WSEncryptionPart("Signature", WSConstants.SIG_NS, "Element");
WSEncryptionPart encryptionBodyPart = new WSEncryptionPart("Body", WSConstants.URI_SOAP11_ENV, "Content");
encryptionParts.add(encryptionBodyPart);
encryptionParts.add(encryptionSignaturePart);
encrypt.setParts(encryptionParts);
encrypt.build(soapMessageDocument, crypto, securityHeader);
*/

DOMSource domSource = new DOMSource(soapMessageDocument);
soapMessage.getSOAPPart().setContent(domSource);

soapMessage.saveChanges();
ByteArrayOutputStream out = new ByteArrayOutputStream();
soapMessage.writeTo(out);
String strMsg = new String(out.toByteArray());
return strMsg;
}
}

将代码放在 com\example\wss\SOAPSecurity.java 文件中

将 wss4j-1.6.18.jar 放在同一个目录中。
http://archive.apache.org/dist/ws/wss4j/1.6.18/

我用这个 .sh 脚本编译/构建/部署了它(你可以使用 cygwin):
/cygdrive/c/Program\ Files\ \(x86\)/Java/jdk1.8.0_73/bin/javac.exe -cp wss4j-1.6.18.jar com/example/wss/SOAPSecurity.java
cp SOAPSecurity.jar SOAPSecurity.jar.bak$1
zip -r test.zip com/
mv test.zip SOAPSecurity.jar
cp SOAPSecurity.jar /cygdrive/c/Program\ Files\ \(x86\)/apache-jmeter-3.0/lib/

使用 .bat 文件运行 JMeter 3.0

-> SOAPSecurity.jar 应该在 apache-jmeter-3.0/lib/文件夹中

-> 我在 JMeter 的 system.properties 文件中也有这些配置:
-Djavax.net.ssl.keyStore=C:/path/to/client.jks
-Djavax.net.ssl.keyStorePassword=verySecret

-> 并在 JMeter 的soap 请求中添加了一个keystore 配置元素

所以,就是这样,请随意尝试一下,让我知道它是否对您有用,如果没有,我可能会提供一些帮助,如果您想调试自己,一个很好的方法是适应/将 System.out.println 放在自定义类中,它提供了关于正在发生的事情的非常有用的信息,并且可以挽救生命,

继续玩得开心!!!

S。

关于soap - 在 Apache JMeter 的 SOAP 请求中添加签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34813720/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com