webentwicklung-frage-antwort-db.com.de

SSLHandshakeException: Es sind keine alternativen Antragstellernamen vorhanden

Ich rufe den HTTPS SOAP Webdienst über Java Code auf. Ich habe bereits ein selbstsigniertes Zertifikat in den jre cacerts Keystore importiert. Jetzt erhalte 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 des in cert angegebenen CN überein. Ich habe über eine Problemumgehung beim Definieren eines benutzerdefinierten Hostnamen-Verifizierers gelesen hier . Aber ich kann nicht machen, wo ich die Problemumgehung 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 Problemumgehungen behoben werden kann, schlagen pls vor.

56
shashankaholic

Danke, Bruno, dass du mir den gebräuchlichen Namen und den alternativen Antragstellernamen mitgeteilt hast. Wie wir herausgefunden haben, wurde das Zertifikat mit CN mit dem DNS-Namen des Netzwerks generiert und um die Wiederherstellung eines neuen Zertifikats mit dem Eintrag für den alternativen Antragstellernamen, d. H. San = ip: 10.0.0.1, gebeten. Welches ist die tatsächliche Lösung.

Es ist uns jedoch gelungen, eine Problemumgehung zu finden, mit der wir in der Entwicklungsphase arbeiten können. Fügen Sie einfach einen statischen Block in die Klasse ein, aus der die SSL-Verbindung hergestellt wird.

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 zufällig Java 8 verwenden, gibt es eine viel schnellere Möglichkeit, das gleiche Ergebnis zu erzielen:

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

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

Bei Verwendung eines Hostnamens kann auf den allgemeinen Namen im Antragstellernamen des Serverzertifikats zurückgegriffen werden, anstatt den alternativen Antragstellernamen zu verwenden.

Bei Verwendung einer IP-Adresse muss im Zertifikat ein Eintrag für einen alternativen Antragstellernamen (vom Typ IP-Adresse, nicht DNS-Name) vorhanden sein.

Weitere Informationen zur Spezifikation und zum Generieren eines solchen Zertifikats finden Sie in diese Antwort .

31
Bruno