XMLデジタル署名仕様に従って着信SOAPメッセージを検証する必要があるJAX-WSWebサービスを開発しています。着信マッサージを操作して、参照beferore署名に対して行われ、XMLドキュメントに報告されていないいくつかの変換を一致させる必要があります。私はこれを行うためにJDOMを使用します。奇妙な動作に気づきました。最初の着信メッセージを検証できますが、後続のメッセージ(署名と参照の両方)で検証が失敗します。Application Server(Websphere)を再起動すると、最初のメッセージを検証できます。この問題は、サブシーケンスWebサービスの呼び出し間で共有されるダーティデータに関連していますか?
次に、SOAPハンドラーの実装を示します。
@Override
public boolean handleMessage(SOAPMessageContext messageContext) {
// get the message from the context
SOAPMessage message = messageContext.getMessage();
// is an outgoing message?
Boolean isOutgoing = (Boolean) messageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if(!isOutgoing){
// incoming message...
// Retrieve the SOAP part of the incoming message
SOAPPart soapPart = message.getSOAPPart();
InputStream inStream = null;
try {
Document doc = null;
// Retrieve the SOAP Envelope of the incoming message
Source source = soapPart.getContent();
inStream = ((StreamSource)source).getInputStream();
// Instantiate a Document containing the SOAP Envelope
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.parse(inStream);
// Use JDOM to retrieve the CommandMessage element and add the xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" namespace declaration
org.jdom2.input.DOMBuilder jdomBuilder = new org.jdom2.input.DOMBuilder();
org.jdom2.Document jdomDocument = jdomBuilder.build(doc);
org.jdom2.Element jdomBodyElement = jdomDocument.getRootElement().getChild("Body", org.jdom2.Namespace.getNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/"));
org.jdom2.Element jdomCommandMessageElement = jdomBodyElement.getChild("CommandMessage", org.jdom2.Namespace.getNamespace("", "http://www.cryptomathic.com/ckms"));
jdomCommandMessageElement.addNamespaceDeclaration(org.jdom2.Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"));
// Instantiate W3C Document to be validated
org.jdom2.Document jdomSignedDocument = new org.jdom2.Document(jdomCommandMessageElement.detach());
org.jdom2.output.DOMOutputter outputter = new org.jdom2.output.DOMOutputter();
Document signedDocument = outputter.output(jdomSignedDocument);
// Find Signature element
NodeList nl = signedDocument.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
// Create a DOMValidateContext and specify a KeyValue KeySelector and document context
DOMValidateContext valContext = new DOMValidateContext(new KeyValueKeySelector(), nl.item(0));
// Create a DOM XMLSignatureFactory that will be used to unmarshal the
// document containing the XMLSignature
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
// unmarshal the XMLSignature
XMLSignature signature = fac.unmarshalXMLSignature(valContext);
boolean coreValidity = signature.validate(valContext);
// Check core validation status
if (coreValidity == false) {
System.out.println("Signature failed core validation");
boolean sv = signature.getSignatureValue().validate(valContext);
System.out.println("signature validation status: " + sv);
// check the validation status of each Reference
Iterator i = signature.getSignedInfo().getReferences().iterator();
for (int j=0; i.hasNext(); j++) {
Reference ref = (Reference) i.next();
boolean refValid = ref.validate(valContext);
System.out.println("ref["+j+"] validity status: " + refValid);
}
} else {
System.out.println("Signature passed core validation");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
inStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return true;
}
そして、これが最初のリクエストのコンソール出力です。
署名はコア検証に合格しました
ただし、後続のリクエストの場合:
署名がコア検証に失敗しました
署名検証ステータス:false
ref [0]有効性ステータス:false
よろしく、ジョバンニ