SSLHandshakeException:不存在主题替代名称

sha*_*lic 56 java ssl https tomcat soap

我通过java代码调用HTTPS SOAP Web服务.我已经在jre cacerts密钥库中导入了自签名证书.现在我得到:

com.sun.xml.internal.ws.com.client.ClientTransportException: HTTP transport error: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present
Run Code Online (Sandbox Code Playgroud)

服务URL的主机名与cert中提供的CN的主机名不匹配.我在这里阅读了有关定义自定义主机名验证程序的解决方法.但我无法在我的代码中实现解决方法的位置.

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;
}
Run Code Online (Sandbox Code Playgroud)

请忽略WSBean参数,因为命名空间和其他wsdl属性来自此bean.如果这个异常可以通过一些不同的解决方法解决,请建议.

sha*_*lic 92

谢谢,布鲁诺让我了解公共名称和主题替代名称.我们发现证书是使用带有DNS名称的网络的CN生成的,并要求使用主题备用名称条目(即san = ip:10.0.0.1)重新生成新证书.这是实际的解决方案.

但是,我们设法找到了一个可以在开发阶段运行的解决方法.只需在我们进行ssl连接的类中添加一个静态块.

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;
            }
        });
}
Run Code Online (Sandbox Code Playgroud)

如果您碰巧使用的是Java 8,那么可以采用更加流畅的方式来实现相同的结果:

static {
    HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> hostname.equals("127.0.0.1"));
}
Run Code Online (Sandbox Code Playgroud)

  • 好.MITM可能会产生具有该IP地址的证书(因为您没有验证它是否与您之后的证书相匹配).这就是说,无论如何,适当的CA都不太可能向IP地址颁发证书. (2认同)

Bru*_*uno 31

与某些浏览器不同,Java在服务器身份验证(RFC 2818,第3.1节)和IP地址方面严格遵循HTTPS规范.

使用主机名时,可以回退到服务器证书的主题DN中的公用名,而不是使用主题备用名.

使用IP地址时,证书中必须有主题备用名称条目(IP地址类型,而不是DNS名称).

您将在此答案中找到有关规范以及如何生成此类证书的更多详细信息.

  • 如果证书中的主机名未解析为该地址,则服务器配置错误.不过,您应该能够更改本地DNS解析,将该名称指向`/ etc/hosts`文件中的此IP地址(如果在Linux下,或其Windows等效项). (4认同)