XML数字签名和JAX-WS

时间:2012-11-26 14:26:16

标签: java xml web-services jax-ws digital-signature

我正在开发一个JAX-WS Web服务,它必须根据XML数字签名规范验证传入的SOAP消息。我必须操纵传入的按摩来匹配对参考beferore签名进行的一些转换,而不是在XML文档中报告。我使用JDOM来做到这一点。我注意到一个奇怪的行为,我可以验证第一个传入的消息,但随后的消息验证失败(在签名和引用上)。如果我重新启动Application Server(Websphere),我可以验证第一条消息。此问题是否与subsequnt Web服务调用之间共享的脏数据有关?

这是SOAP Handler实现:

@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

此致 乔瓦尼

0 个答案:

没有答案