姜依涛 2019-06-21
1.组件版本信息
apache-tomcat-7.0.75
JDK 1.8.0_91
2.使用jdk自带的keytool命令生成keystore文件test.keystore
命令:keytool -genkey -alias test123 -keypass test123 -keyalg RSA -keysize 1024 -keystore test.keystore -storepass test123
3.将test.keystore拷贝到apache-tomcat-7.0.75bin目录下
4.配置tomcat的conf目录server.xml文件,在配置文件中新增SSL配置
<Connector SSLEnabled="true" clientAuth="false" keystoreFile="bin/test.keystore" keystorePass="test123" maxThreads="150" port="8443" protocol="org.apache.coyote.http11.Http11Protocol" scheme="https" secure="true" sslProtocol="TLS"/>
5.将webservice工程添加进tomcat并启动,使用postman访问http和https链接。http可以正常访问,https访问不了,由于客户端证书问题
6.新建类HttpClientTest,用于配置https相关SSL设置
import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLContext; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.TrustStrategy; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.ssl.SSLContextBuilder; public class HttpClientTest { public static CloseableHttpClient createSSLClient() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException { SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial( null, new TrustStrategy() { public boolean isTrusted( X509Certificate[] chain, String authType ) throws CertificateException { return true; } } ).build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslContext, NoopHostnameVerifier.INSTANCE ); return HttpClients.custom().setSSLSocketFactory( sslsf ).build(); } }
7.新建类HttpClientUtil,用于测试https的get请求
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URI; import java.net.URISyntaxException; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import org.apache.commons.logging.Log; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.util.EntityUtils; public class HttpClientUtil { public static void main( String[] args ) throws ClientProtocolException, IOException, URISyntaxException, KeyManagementException, NoSuchAlgorithmException, KeyStoreException { String url = "https://localhost:8443/maven-example/hello"; CloseableHttpClient httpClient = HttpClientTest.createSSLClient(); HttpGet get = new HttpGet(); get.setURI( new URI( url ) ); HttpResponse response = httpClient.execute( get ); String s = streamToString( response.getEntity().getContent() ); System.out.println( s ); } private static String streamToString( InputStream is ) throws IOException { String line = ""; StringBuilder total = new StringBuilder(); BufferedReader rd = new BufferedReader( new InputStreamReader( is ) ); while ( (line = rd.readLine()) != null ) { total.append( line ); } return total.toString(); } }
8.执行main方法,正确输出https的response响应
9.操作过程中遇到一个问题,报主机名验证错误
解决方法:将new SSLConnectionSocketFactory(sslContext)修改为new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE)即可。原理后续进一步研究
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslContext); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslContext, NoopHostnameVerifier.INSTANCE);
创建一个 HttpClient 实例,这个实例需要调用 Dispose 方法释放资源,这里使用了 using 语句。接着调用 GetAsync,给它传递要调用的方法的地址,向服务器发送 Get 请求。