WSS4Jを使用して、キーストアからの証明書を使用してSOAP要求の署名者を作成しています。私のキーストア形式は .pkcs で、すべてが最初の署名で機能しますが、プログラムを実行して複数のドキュメントに署名しようとすると、キーストアに証明書が見つかりません。署名中に証明書が消費される可能性があるように思えます。つまり、現在の環境では証明書が存在しなくなっていることを意味します。プログラムが停止して再起動すると、最初のリクエストに署名しますが、2 番目のリクエストは失敗します。何度も通ったのですが、原因がわかりません。このコードは、証明書がキーストアから消える前に最後に呼び出されるものです。this.certUri = getWsConfig().getIdAllocator().createSecureId("X509-", certs[0]);
これは の 556 行にありWSSecSignature.class
ます。これが私のコードです。
package com.soapsigner;
import java.io.*;
import java.util.Properties;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.ws.security.*;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.Merlin;
import org.apache.ws.security.message.WSSecHeader;
import org.apache.ws.security.message.WSSecSignature;
import org.apache.ws.security.message.WSSecTimestamp;
import org.w3c.dom.Document;
import org.xml.sax.*;
public class SoapSigner {
private Crypto crypto;
private WSSecSignature sig;
private WSSecTimestamp time;
private WSSecHeader header;
private String alias;
private String password;
private String keyFile;
private String keyFileType;
private Document signedDoc;
private String lastError;
{
Logger rootLogger = Logger.getRootLogger();
rootLogger.setLevel(Level.INFO);
rootLogger.addAppender(new ConsoleAppender(
new PatternLayout("%-6r [%p] %c - %m%n")));
}
//constructor
public SoapSigner(String XML){
try {
alias = "myalias";
password = "mypassword";
keyFile = "/keystore/mykeystore.pkcs";
keyFileType = "pkcs12";
sig = new WSSecSignature();
time = new WSSecTimestamp();
header = new WSSecHeader();
signedDoc = null;
lastError = "";
Merlin merlin = new Merlin(getCryptoProperties());
System.out.println("real signing keystore object: "+merlin.getKeyStore().getCertificate(alias).toString().length()); //Passed
crypto = merlin;
signDocument(xmlToDoc(XML));
Merlin test = new Merlin(getCryptoProperties());
System.out.println("test keystore object: "+test.getKeyStore().getCertificate(alias).toString().length()); //Failed, this is null
} catch (Exception e) {
setLastError(e);
}
}
//properties
public Properties getCryptoProperties(){
Properties cryptoProperties = new Properties();
cryptoProperties.setProperty("org.apache.ws.security.crypto.merlin.keystore.alias", alias);
cryptoProperties.setProperty("org.apache.ws.security.crypto.merlin.keystore.password", password);
cryptoProperties.setProperty("org.apache.ws.security.crypto.merlin.keystore.type", keyFileType);
cryptoProperties.setProperty("org.apache.ws.security.crypto.merlin.keystore.file", keyFile);
return cryptoProperties;
}
//sign the document
public void signDocument(Document doc){
try {
header.setMustUnderstand(true);
sig.setSignatureAlgorithm(WSConstants.C14N_EXCL_OMIT_COMMENTS);
sig.setSignatureAlgorithm(WSConstants.RSA);
sig.setUserInfo(alias, password);
sig.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
header.insertSecurityHeader(doc);
sig.build(doc, crypto, header);
time.build(doc, header);
signedDoc = doc;
} catch (Exception e) {
setLastError(e);
}
}
//get the signed document
public Document getDocument(){
return signedDoc;
}
//get the signed xml
public String getXML(){
return getStringFromDoc(getDocument()).trim();
}
//get last error
public String getLastError(){
return lastError;
}
//set last error
private void setLastError(Throwable e){
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
lastError += " NEXT ERROR "+sw.toString();
e.printStackTrace();
}
//document to string
public String getStringFromDoc(Document doc){
try
{
DOMSource domSource = new DOMSource(doc);
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(domSource, result);
writer.flush();
return writer.toString();
}
catch(Exception e)
{
setLastError(e);
return null;
}
}
//string to document
public Document xmlToDoc(String XML){
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db;
db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(XML));
Document doc = db.parse(is);
return doc;
} catch (Exception e) {
setLastError(e);
return null;
}
}
//main
public static void main(String[] args){
String XML1 = "<?xml version='1.0' encoding='UTF-8'?><soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> <soap:Body> <test1></test1> </soap:Body> </soap:Envelope>";
String XML2 = "<?xml version='1.0' encoding='UTF-8'?><soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> <soap:Body> <test2></test2> </soap:Body> </soap:Envelope>";
new SoapSigner(XML1);
new SoapSigner(XML2);
}
}
また、doDebug モードをオンにしたいのですがWSSecBase.class
、値を切り替えるために変数ビューアーに表示されません。コンストラクターでブレークポイントを作成し、それを監視するように設定しましたが、トグルしても表示されません。