一、单向认证流程
单向认证流程中,服务器端保存着公钥证书和私钥两个文件,整个握手过程如下:
 
- 客户端发起建立HTTPS连接请求,将SSL协议版本的信息发送给服务器端;
- 服务器端将本机的公钥证书(server.crt)发送给客户端;
- 客户端读取公钥证书(server.crt),取出了服务端公钥;
- 客户端生成一个随机数(密钥R),用刚才得到的服务器公钥去加密这个随机数形成密文,发送给服务端;
- 服务端用自己的私钥(server.key)去解密这个密文,得到了密钥R
- 服务端和客户端在后续通讯过程中就使用这个密钥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);
        }
    }
}
参考文章:
更多内容关注微信公众号 ”前后端技术精选“,或者语雀,里面有更多知识:https://www.yuque.com/riverzmm/uu60c9?# 《安全》> 更多内容关注微信公众号 ”前后端技术精选“,或者语雀,里面有更多知识:https://www.yuque.com/riverzmm/uu60c9?# 《安全》> 更多内容关注微信公众号 ”前后端技术精选“,或者语雀,里面有更多知识:https://www.yuque.com/riverzmm/uu60c9?# 《安全》> 更多内容关注微信公众号 ”前后端技术精选“,或者语雀,里面有更多知识:https://www.yuque.com/riverzmm/uu60c9?# 《安全》



















