使用 X509 证书验证 SOAP 请求

Verify SOAP request using the X509 certificate

我有一个 SOAP 服务器。服务器接收的 SOAP 请求具有 ws 安全性 headers。以下是请求的主要节点XML.

  1. BinarySecurityToken(X509PKIPathv1 证书)
  2. 摘要方法
  3. 摘要值
  4. 签名值
  5. SecurityTokenReference

  6. 数据(由 SOAP 中的客户端 body)

我必须使用客户端(请求的发送者)提供的证书(.cer 文件)验证请求。

验证请求的步骤是什么?请解释一下这个概念。没有库可用于执行此操作。经过长时间的研究,我能够将 BinarySecurityTokenbase64_encode($certFile) 匹配 $certFile 是请求者的证书。现在正在研究怎么把DigestValue和what.

匹配起来

WS-Security headers可以通过以下验证。我为此编写了一个实用程序。看看它。

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.StringReader;
import java.security.KeyStore;
import java.security.Provider;
import java.security.PublicKey;
import java.security.cert.X509Certificate;

import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;


public class WSUtil {
    public static void main(String[] args) throws Exception {

        String req = "SOAPMESSAGE";
        Document p = createXMLDocument(req);
        InputStream inStream = new FileInputStream("certificate.p12"); //Provide your certificate file

        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(inStream, "pass".toCharArray()); //Certificate password - pass

        String alias = ks.aliases().nextElement();
        X509Certificate certificate = (X509Certificate) ks.getCertificate(alias);

        validateSignature(p.getElementsByTagName("ds:Signature").item(0),p.getElementsByTagName("soapenv:Body").item(0),certificate.getPublicKey());//True if the message is valid
    }

    public static Document createXMLDocument(String xmlString) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        DocumentBuilder builder;
        Document document = null;
        try {
            builder = factory.newDocumentBuilder();
            document = builder.parse(new InputSource(
                    new StringReader(xmlString)));
        } catch (Exception e) {
            throw e;
        }
        return document;
    }

    private static boolean validateSignature(Node signatureNode, Node bodyTag, PublicKey publicKey) {
        boolean signatureIsValid = false;
        try {
            // Create a DOM XMLSignatureFactory that will be used to unmarshal the
            // document containing the XMLSignature
            String providerName = System.getProperty
                    ("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI");
            XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM",
                    (Provider) Class.forName(providerName).newInstance());

            // Create a DOMValidateContext and specify a KeyValue KeySelector
            // and document context
            DOMValidateContext valContext = new DOMValidateContext(new X509KeySelector(publicKey), signatureNode);
            valContext.setIdAttributeNS((Element) bodyTag, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "Id");

            // Unmarshal the XMLSignature.
            XMLSignature signature = fac.unmarshalXMLSignature(valContext);
            // Validate the XMLSignature.
            signatureIsValid = signature.validate(valContext); 

        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return signatureIsValid;
    }
}

备注 您必须按原样提供 SOAP 消息。你不应该在某处做任何 XML 格式或任何空 space 。添加安全性的 SOAP 消息非常敏感。即使是末尾的 space 也会使 SOAP 消息无效。

X509KeySelector 构造函数类型不正确