Java实现HTTPS请求及证书证书验证(附源码)

Java实现HTTPS请求及证书证书验证(附源码)

欢迎大家访问我的GitHub博客

https://lunan0320.github.io/

 

先发布一个初始的版本,主要以代码为主,具体的细节将之后更新。

 

服务器流程环节:

1、在本机服务器上生成一个自定义证书,格式为jks格式。
2、将自定义证书添加到客户端的信任的根证书库中,Windows系统中可以直接win+R 输入mmc即可找到添加区域。(一定是添加到信任的根证书中)
3、服务器初始化创建SSLContext上下文类型,这个过程包括创建密钥管理库和信任库两部分,使用的是SUN509的套件。
4、创建一个SSLContext的对象,初始化时使用TLSv1协议。创建两个密钥管理库和信任库的实例,作为初始化SSLContext的参数。
5、ServerFactory创建一个SSLServerSocket
6、开始接受客户端发来的请求, sslServerSocket.accept()
      1)如果没有请求就阻塞掉;
      2)如果接收到请求就创建一个线程去处理它

 
一、服务器实现代码如下:

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.security.KeyStore;
 
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
 
public class HTTPSServer {
    private int port = 446;
    private boolean isServerDone = false;
     
    public static void main(String[] args){
        HTTPSServer server = new HTTPSServer();
        server.run();
    }
     
    HTTPSServer(){      
    }
     
    HTTPSServer(int port){
        this.port = port;
    }
     
    // 创建并初始化 SSLContext
    private SSLContext createSSLContext(){
        try{
            KeyStore keyStore = KeyStore.getInstance("JKS");
            keyStore.load(new FileInputStream("Server.jks"),"passwd".toCharArray());
             
            //创建密钥管理器
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
            keyManagerFactory.init(keyStore, "passwd".toCharArray());
            KeyManager[] km = keyManagerFactory.getKeyManagers();
             
            // 创建信任库
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
            trustManagerFactory.init(keyStore);
            TrustManager[] tm = trustManagerFactory.getTrustManagers();
             
            //初始化 SSLContext
            SSLContext sslContext = SSLContext.getInstance("TLSv1");
            sslContext.init(km,  tm, null);
             
            return sslContext;
        } catch (Exception ex){
            ex.printStackTrace();
        }
         
        return null;
    }
     
    // 开启服务器
    public void run(){
        SSLContext sslContext = this.createSSLContext();
         
        try{
            // 创建服务器的 socket factory
            SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();
             
            // 创建一个服务器Socket
            SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(this.port);
             
            System.out.println("SSL服务器已开启~");
            while(!isServerDone){
                SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
                 
                // Start the server thread
                new ServerThread(sslSocket).start();
            }
        } catch (Exception ex){
            ex.printStackTrace();
        }
    }
     
    // 处理从客户端来的Socket请求
    static class ServerThread extends Thread {
        private SSLSocket sslSocket = null;
         
        ServerThread(SSLSocket sslSocket){
            this.sslSocket = sslSocket;
        }
         
        public void run(){
            sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());
             
            try{
                // Start handshake
                sslSocket.startHandshake();
                 
                // 输出一些Session信息
                SSLSession sslSession = sslSocket.getSession();
                 
                System.out.println("SSLSession :");
                System.out.println("\tProtocol : "+sslSession.getProtocol());
                System.out.println("\tCipher suite : "+sslSession.getCipherSuite());
                 
                // 定义输入输出流
                InputStream inputStream = sslSocket.getInputStream();
                OutputStream outputStream = sslSocket.getOutputStream();
                 
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(outputStream));
                 
                String line = null;
                while((line = bufferedReader.readLine()) != null){
                    System.out.println("Inut : "+line);
                     
                    if(line.trim().isEmpty()){
                        break;
                    }
                }
                 
             
                printWriter.print("This is server");
                printWriter.flush();
                 
                sslSocket.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}

 

 

客户端流程环节:

1、在客户都添加服务器自定义证书,格式为jks格式。
2、客户端初始化创建SSLContext上下文类型,这个过程包括创建密钥管理库和信任库两部分,使用的是SUN509的套件。
3、创建一个SSLContext的对象,初始化时使用TLSv1协议。创建两个密钥管理库和信任库的实例,作为初始化SSLContext的参数。
4、通过SocketFactory创建一个SSLSocket,IP地址和port均为服务器的。
5、证书验证

sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());
交换密钥套件的过程。

在这个过程中客户端会将服务器发来的证书与本地的证书去验证
如果是保存在本地的服务器证书,则验证通过,否则证书验证不通过。
6、握手过程

sslSocket.startHandshake();

可以设置个断点进去看看,或者抓包分析一下,包括了TCP三次握手的过程。

7、连接建立完成后,即可安全交互。
 
 
二、客户端代码如下

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.security.KeyStore;
 
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
 
public class HTTPSClient {
    private String host = "192.168.**.**";
    private int port = 446;
     
    public static void main(String[] args){
        HTTPSClient client = new HTTPSClient();
        client.run();
    }
     
    HTTPSClient(){      
    }
     
    HTTPSClient(String host, int port){
        this.host = host;
        this.port = port;
    }
     
    // 创建并初始化 SSLContext
    private SSLContext createSSLContext(){
        try{
            KeyStore keyStore = KeyStore.getInstance("JKS");
            keyStore.load(new FileInputStream("Server.jks"),"passwd".toCharArray());
             
            // 创建一个密钥管理器
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
            keyManagerFactory.init(keyStore, "passphrase".toCharArray());
            KeyManager[] km = keyManagerFactory.getKeyManagers();
             
            //创建一个信任库
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
            trustManagerFactory.init(keyStore);
            TrustManager[] tm = trustManagerFactory.getTrustManagers();
             
            // 初始化SSLContext
            SSLContext sslContext = SSLContext.getInstance("TLSv1");
            sslContext.init(km,  tm, null);
             
            return sslContext;
        } catch (Exception ex){
            ex.printStackTrace();
        }
         
        return null;
    }
     
    // 开启客户端程序
    public void run(){
        SSLContext sslContext = this.createSSLContext();
         
        try{
            //创建Socket factory
            SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
             
            // 创建一个客户端的SSLsocket
            SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(this.host, this.port);
             
            System.out.println("SSL 客户端开启");
            new ClientThread(sslSocket).start();
        } catch (Exception ex){
            ex.printStackTrace();
        }
    }
     
    // Thread handling the socket to server
    static class ClientThread extends Thread {
        private SSLSocket sslSocket = null;
         
        ClientThread(SSLSocket sslSocket){
            this.sslSocket = sslSocket;
        }
         
        public void run(){
            sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());
             
            try{
                // 握手过程
                sslSocket.startHandshake();
                 
                // 输出关于Session的信息
                SSLSession sslSession = sslSocket.getSession();
                 
                System.out.println("SSLSession :");
                System.out.println("\tProtocol : "+sslSession.getProtocol());
                System.out.println("\tCipher suite : "+sslSession.getCipherSuite());
                 
                // Start handling application content
                InputStream inputStream = sslSocket.getInputStream();
                OutputStream outputStream = sslSocket.getOutputStream();
                 
                 //定义输入以及输出缓冲区
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(outputStream));
                 
                printWriter.println("This is client");
                printWriter.println();
                printWriter.flush();
                 
                String line = null;
                while((line = bufferedReader.readLine()) != null){
                    if(line.trim().equals("This is Client~")){
                        break;
                    }
                }
                 
                sslSocket.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}

你可能感兴趣的:(JAVA,HTTPS,java,https,ssl,ca证书)