基于Spring Boot实现HTTPS方式请求下客户端与服务端进行单向认证与双向认证的实例
证书
首先准备服务端和客户端的证书。
服务端
如果是云服务器,服务端可直接由提供商生成,否则执行下面的代码生成
1、生成服务端sslServer.p12文件
1
| keytool -genkey -v -alias sslServer -keyalg RSA -storetype PKCS12 -keystore E:\learning-demo\sslServer.p12
|
2、导出服务端公钥sslServer.cer 文件
1
| keytool -keystore E:\learning-demo\sslServer.p12 -export -alias sslServer -file E:\learning-demo\sslServer.cer
|
在生成过程中,需要注意的一点是,第一步中“您的名字与姓氏是什么”应该填服务器的ip或对应系统的域名,这样在后面代码中校验证书就能直接通过,若填写的不一致,则需要在代码中默认允许校验自己通过。
客户端
1、生成客户端sslClient.p12文件
1
| keytool -genkey -v -alias sslClient -keyalg RSA -storetype PKCS12 -keystore E:\learning-demo\sslClient.p12
|
2、导出客户端公钥sslClient.cer 文件
1
| keytool -keystore E:\learning-demo\sslClient.p12 -export -alias sslClient -file E:\learning-demo\sslClient.cer
|
导入双方系统的jre运行环境的cacerts证书库
将Client端和Server端的公钥文件(.cer文件)导入双方系统的jre运行环境的cacerts证书库(双向认证需要操作此步骤)
将客户端公钥导入的服务端jdk信任库
1
| keytool -import -alias sslClient -file E:\learning-demo\sslClient.cer -keystore D:\jdk\jre\lib\security\cacerts –v
|
将服务端公钥导入到客户端的jdk信任库
1
| keytool -import -alias sslServer -file E:\learning-demo\sslServer.cer -keystore D:\jdk\jre\lib\security\cacerts –v
|
将客户端公钥导入到服务端Server.p12证书库
1
| keytool -import -alias sslClient -v -file E:\learning-demo\sslClient.cer -keystore D:\jdk\sslServer.p12
|
单向认证
1 2 3 4
| server.ssl.key-store=classpath:sslServer.p12 server.ssl.key-store-password=123456 server.ssl.key-alias=sslServer server.ssl.keyStoreType=JKS
|
随便访问项目中的一个接口,如果页面出现下面的提示信息,则表示单向认证开启成功。
双向认证
1 2 3 4
| server.ssl.trust-store-password=123456 server.ssl.client-auth=need server.ssl.trust-store-type=JKS server.ssl.trust-store-provider=SUN
|
客户端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| private final static String TEST_URL = "https://127.0.0.1:7090/server/ssl"; @Test public void getHKVesselTrip() throws Exception { KeyStore clientStore = KeyStore.getInstance("PKCS12"); clientStore .load(new FileInputStream("E:\\learning-demo\\sslClient.p12"), "123456".toCharArray()); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(clientStore, "123456".toCharArray()); KeyManager[] kms = kmf.getKeyManagers(); TrustManagerFactory tmf = TrustManagerFactory .getInstance(TrustManagerFactory.getDefaultAlgorithm()); KeyStore trustStore = KeyStore.getInstance("JKS"); trustStore.load(new FileInputStream("D:\\jdk\\jre\\lib\\security\\cacerts"), "changeit".toCharArray()); tmf.init(trustStore); TrustManager[] tms = tmf.getTrustManagers(); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(kms, tms, new SecureRandom()); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); try { HttpGet httpget = new HttpGet(TEST_URL); System.out.println("executing request" + httpget.getRequestLine()); CloseableHttpResponse response = httpclient.execute(httpget); try { HttpEntity entity = response.getEntity(); if (entity != null) { System.out.println(EntityUtils.toString(entity)); } } finally { response.close(); } } finally { httpclient.close(); } }
|