06-HTTPS单向认证及Java案例

780 阅读2分钟

01-从HTTP到HTTPS

02-HTTPS证书生成、验签 、证书链

03-OpenSSL-创建带SAN扩展的证书并进行CA自签

04-HTTPS证书格式及转换

05-HTTPS 秘钥库与证书(Java)

06-HTTPS单向认证及Java案例

07-HTTPS双向认证及Java案例

08-HTTPS在HTTPClient的应用

10-HTTPS在Nginx中的配置

11-HTTPS在SpringBoot中的配置

12-HTTPS在Tomcat配置

13-SSL-Mysql配置与应用

14-HTTPS在Redis中的配置

15-HTTPS基于Feign的远程调用

16-HTTPS在Eureka中的配置

一、单向认证流程

单向认证流程中,服务器端保存着公钥证书和私钥两个文件,整个握手过程如下:

  1. 客户端发起建立HTTPS连接请求,将SSL协议版本的信息发送给服务器端;
  2. 服务器端将本机的公钥证书(server.crt)发送给客户端;
  3. 客户端读取公钥证书(server.crt),取出了服务端公钥;
  4. 客户端生成一个随机数(密钥R),用刚才得到的服务器公钥去加密这个随机数形成密文,发送给服务端;
  5. 服务端用自己的私钥(server.key)去解密这个密文,得到了密钥R
  6. 服务端和客户端在后续通讯过程中就使用这个密钥R进行通信了。

二、Java代码

选择使用单向认证,这种情况下client侧不需要提供证书。所以, server侧只需要自己的keystore文件,不需要truststore文件 client侧不需要自己的keystore文件,只需要truststore文件(其中包含server的公钥)。 此外server侧需要在创建SSLServerSocket之后设定不需要客户端证书:setNeedClientAuth(false)

其中生成证书的命令可以查看 02-HTTPS证书生成、验签 、证书链

server代码

 public class CatServerNoClientAuth implements Runnable, HandshakeCompletedListener {
 ​
     public static final int SERVER_PORT = 11123;
 ​
     private final Socket _s;
 ​
     public CatServerNoClientAuth(Socket s) {
         _s = s;
     }
 ​
     public static void main(String[] args) throws Exception {
         String serverKeyStoreFile = "D:\code\mycode\java-study\https\src\main\resources\server.p12";
         String serverKeyStorePwd = "huawei";
         String catServerKeyPwd = "huawei";
 ​
         KeyStore serverKeyStore = KeyStore.getInstance("JKS");
         serverKeyStore.load(new FileInputStream(serverKeyStoreFile), serverKeyStorePwd.toCharArray());
 ​
         KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
         kmf.init(serverKeyStore, catServerKeyPwd.toCharArray());
 ​
         SSLContext sslContext = SSLContext.getInstance("TLSv1");
         sslContext.init(kmf.getKeyManagers(), null, null);
 ​
         SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();
         SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(SERVER_PORT);
         sslServerSocket.setNeedClientAuth(false);
 ​
         while (true) {
             SSLSocket s = (SSLSocket) sslServerSocket.accept();
             CatServerNoClientAuth cs = new CatServerNoClientAuth(s);
             s.addHandshakeCompletedListener(cs);
             new Thread(cs).start();
         }
     }
 ​
     @Override
     public void run() {
         try {
             BufferedReader reader = new BufferedReader(new InputStreamReader(_s.getInputStream()));
             PrintWriter writer = new PrintWriter(_s.getOutputStream(), true);
 ​
             writer.println("Welcome~, enter exit to leave.");
             String s;
             while ((s = reader.readLine()) != null && !s.trim().equalsIgnoreCase("exit")) {
                 writer.println("Echo: " + s);
             }
             writer.println("Bye~");
         } catch (Exception e) {
             e.printStackTrace();
         } finally {
             try {
                 _s.close();
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
     }
 ​
     @Override
     public void handshakeCompleted(HandshakeCompletedEvent event) {
         try {
             X509Certificate cert = (X509Certificate) event.getPeerCertificates()[0];
         } catch (SSLPeerUnverifiedException ex) {
             System.out.println("handshakeCompleted, SSLPeerUnverified.");
         }
     }
 }

client代码

 public class FoxClientNoClientAuth {
     public static void main(String[] args) throws Exception {
         String clientTrustKeyStoreFile = "D:\code\mycode\java-study\https\src\main\resources\root.p12";
         String clientTrustKeyStorePwd = "huawei";
 ​
         KeyStore clientTrustKeyStore = KeyStore.getInstance("JKS");
         clientTrustKeyStore.load(new FileInputStream(clientTrustKeyStoreFile), clientTrustKeyStorePwd.toCharArray());
 ​
         TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
         tmf.init(clientTrustKeyStore);
 ​
         SSLContext sslContext = SSLContext.getInstance("TLSv1");
         sslContext.init(null, tmf.getTrustManagers(), null);
 ​
         SSLSocketFactory socketFactory = sslContext.getSocketFactory();
         Socket socket = socketFactory.createSocket("localhost", 11123);
 ​
         PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
         BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
 ​
         send("hello", out);
         send("exit", out);
         receive(in);
         socket.close();
     }
 ​
     public static void send(String s, PrintWriter out) throws IOException {
         System.out.println("Sending: " + s);
         out.println(s);
     }
 ​
     public static void receive(BufferedReader in) throws IOException {
         String s;
         while ((s = in.readLine()) != null) {
             System.out.println("Reveived: " + s);
         }
     }
 }
 ​

参考文章:

更多内容关注微信公众号 ”前后端技术精选“,或者语雀,里面有更多知识:www.yuque.com/riverzmm/uu… 《安全》