【トラブル】【Tomcat】Tomcat - Javaアプリでの SSL通信時のトラブル

■サーバ側で「IllegalStateException」が発生する

エラー内容

重大: 
java.lang.IllegalStateException
	at org.apache.tomcat.util.net.AbstractEndpoint.getSSLHostConfig(AbstractEndpoint.java:266)
	at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLEngine(AbstractJsseEndpoint.java:138)
	at org.apache.tomcat.util.net.SecureNioChannel.processSNI(SecureNioChannel.java:316)
	at org.apache.tomcat.util.net.SecureNioChannel.handshake(SecureNioChannel.java:174)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1432)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:744)

原因

* 本当の原因じゃないと思う。あくまで一時しのぎ
http://www.lookatsrc.com/source/org/apache/tomcat/util/net/AbstractEndpoint.java?a=org.apache.tomcat.embed:tomcat-embed-core
より抜粋

protected SSLHostConfig getSSLHostConfig(String sniHostName) {
    SSLHostConfig result = null;
    
    // 略
    
    if (result == null) {
        result = sslHostConfigs.get(getDefaultSSLHostConfigName()); // ★ここでNullを返させなくては例外が発生しない★
    }
    if (result == null) {
        // Should never happen.
        throw new IllegalStateException();
    }

解決案

* 本当の解決策じゃないと思う。あくまで一時しのぎ
 * server.xmlで、defaultSSLHostConfigName="【ホスト名】"を追加する
 * defaultSSLHostConfigNameについては、以下のサイトを参照。
https://tomcat.apache.org/migration-85.html
* 修正前
<Connector SSLEnabled="true" maxThreads="150" port="8443" 
 protocol="org.apache.coyote.http11.Http11NioProtocol">
* 修正後
<Connector SSLEnabled="true" maxThreads="150" port="8443" 
 protocol="org.apache.coyote.http11.Http11NioProtocol"
 defaultSSLHostConfigName="localhost">
詳細は以下の関連記事を参照のこと。
http://blogs.yahoo.co.jp/dk521123/36513426.html

■サーバ側で「CertificateException: No name matching ホスト名 found」が発生する

エラー内容

javax.xml.ws.WebServiceException: 次の場所でWSDLへのアクセスに失敗しました: https://localhost:8443/SampleWebService/services/SampleWebService.ws?wsdl。次のメッセージにより失敗しました: 
	java.security.cert.CertificateException: No name matching localhost found。
	at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.tryWithMex(RuntimeWSDLParser.java:250)
	at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:231)
	at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:194)
	at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:163)
	at com.sun.xml.internal.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:348)
	at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:306)
	at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:215)
	at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:196)
	at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:192)
	at com.sun.xml.internal.ws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:99)
	at javax.xml.ws.Service.<init>(Service.java:77)
	at com.sample.webservice.client.stub.SampleWebServiceService.<init>(SampleWebServiceService.java:50)
	at com.sample.webservice.client.stub.Main.main(Main.java:47)
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching localhost found
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
	at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1917)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:301)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:295)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1369)
	at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:156)
	at sun.security.ssl.Handshaker.processLoop(Handshaker.java:925)
	at sun.security.ssl.Handshaker.process_record(Handshaker.java:860)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1043)
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1343)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1371)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1355)
	at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1511)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1439)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
	at java.net.URL.openStream(URL.java:1038)
	at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.createReader(RuntimeWSDLParser.java:984)
	at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.resolveWSDL(RuntimeWSDLParser.java:385)
	at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:216)
	... 11 more
Caused by: java.security.cert.CertificateException: No name matching localhost found
	at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:208)
	at sun.security.util.HostnameChecker.match(HostnameChecker.java:93)
	at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455)
	at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:436)
	at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:200)
	at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1351)
	... 27 more

解決案

 * クライアント側でSSL通信用の処理を追加する(以下の★SSL通信用の処理★を参照)
http://blogs.yahoo.co.jp/dk521123/36516080.html

関連記事

Tomcat 8.5 で SSL通信 ~簡易版~

http://blogs.yahoo.co.jp/dk521123/36513426.html