57 Stimmen

SSLHandshakeException: Keine alternativen Subjektnamen vorhanden

Ich rufe einen HTTPS SOAP-Webdienst über Java-Code auf. Ich habe bereits ein selbstsigniertes Zertifikat in den Keystore von jre cacerts importiert. Jetzt bekomme ich :

com.sun.xml.internal.ws.com.client.ClientTransportException: HTTP transport error: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present

Der Hostname der Service-URL stimmt nicht mit dem in der Zertifizierung angegebenen CN überein. Ich habe gelesen, dass ein benutzerdefinierter Hostname-Prüfer als Workaround eingesetzt werden kann aquí . Aber ich kann nicht in der Lage zu machen, wo ich die Umgehung in meinem Code implementieren sollte.

public SOAPMessage invokeWS(WSBean bean) throws Exception {

    SOAPMessage response=null;
    try{

    /** Create a service and add at least one port to it. **/
    String targetNameSpace = bean.getTargetNameSpace();
    String endpointUrl = bean.getEndpointUrl();
    QName serviceName = new QName(targetNameSpace, bean.getServiceName());
    QName portName = new QName(targetNameSpace, bean.getPortName());
    String SOAPAction = bean.getSOAPAction();
    HashMap<String, String> map = bean.getParameters();

    Service service = Service.create(serviceName);
    service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointUrl);

    /** Create a Dispatch instance from a service. **/
    Dispatch dispatch = service.createDispatch(portName, SOAPMessage.class,
            Service.Mode.MESSAGE);

    // The soapActionUri is set here. otherwise we get a error on .net based
    // services.
    dispatch.getRequestContext().put(Dispatch.SOAPACTION_USE_PROPERTY,
            new Boolean(true));
    dispatch.getRequestContext().put(Dispatch.SOAPACTION_URI_PROPERTY,
            SOAPAction);

    /** Create SOAPMessage request. **/
    // compose a request message
    MessageFactory messageFactory = MessageFactory.newInstance();
    SOAPMessage message = messageFactory.createMessage();

    // Create objects for the message parts
    SOAPPart soapPart = message.getSOAPPart();
    SOAPEnvelope envelope = soapPart.getEnvelope();
    SOAPBody body = envelope.getBody();

    SOAPElement bodyElement = body.addChildElement(bean.getInputMethod(),
            bean.getPrefix(), bean.getTargetNameSpace());

             ...more code to form soap body goes here

    // Print request
    message.writeTo(System.out);

    // Save the message
    message.saveChanges();

    response = (SOAPMessage)dispatch.invoke(message);
    }
    catch (Exception e) {
        log.error("Error in invokeSiebelWS :"+e);
    }
    return response;
}

Bitte ignorieren Sie den WSBean-Parameter, da die Namespaces und andere Wsdl-Attribute von dieser Bean stammen. Und wenn diese Ausnahme mit einigen verschiedenen Workarounds gelöst werden kann, pls tun vorschlagen.

93voto

shashankaholic Punkte 4094

Danke, Bruno, dass du mich über den Common Name und den Subject Alternative Name informiert hast. Wie wir herausgefunden haben, wurde das Zertifikat mit dem CN mit dem DNS-Namen des Netzwerks generiert und wir baten um die Regeneration des neuen Zertifikats mit dem Eintrag Subject Alternative Name, d.h. san=ip:10.0.0.1. tatsächliche Lösung .

Aber es ist uns gelungen, etwas herauszufinden Abhilfe mit denen wir in der Entwicklungsphase arbeiten können. Fügen Sie einfach einen statischen Block in der Klasse hinzu, von der aus wir die SSL-Verbindung herstellen.

static {
    HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
        {
            public boolean verify(String hostname, SSLSession session)
            {
                // ip address of the service URL(like.23.28.244.244)
                if (hostname.equals("23.28.244.244"))
                    return true;
                return false;
            }
        });
}

Wenn Sie Java 8 verwenden, gibt es einen viel einfacheren Weg, um das gleiche Ergebnis zu erzielen:

static {
    HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> hostname.equals("127.0.0.1"));
}

33voto

Bruno Punkte 114719

Im Gegensatz zu einigen Browsern hält sich Java streng an die HTTPS-Spezifikation, wenn es um die Überprüfung der Serveridentität (RFC 2818, Abschnitt 3.1) und IP-Adressen geht.

Bei der Verwendung eines Hostnamens ist es möglich, auf den Common Name im Subject DN des Serverzertifikats zurückzugreifen, anstatt den Subject Alternative Name zu verwenden.

Bei der Verwendung einer IP-Adresse muss im Zertifikat ein Subject Alternative Name (vom Typ IP-Adresse, nicht DNS-Name) eingetragen sein.

Weitere Einzelheiten über die Spezifikation und die Erstellung eines solchen Zertifikats finden Sie unter diese Antwort .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X