Java SSL通信Demo

Java SSL通信Demo

一、数字证书创建

在SSL通信协议中,服务端必须有一个数字证书,当客户端连接到服务端时,会得到这个证书,然后客户端会判断这个证书是否是可信的,如果是,则交换信道加密密钥,进行通信。如果不信任这个证书,则连接失败。

1、keytool

JDK自带keytool工具命令案列:

keytool 
    -genkey 
    -alias demo
    -keyalg RSA 
    -keysize 1024 
    -validity 365 
    -keystore ./ks 
    -dname "CN=localhost,OU=cn,O=cn,L=cn,ST=cn,C=cn" 
    -storepass ks 
    -keypass 123456
    
参数参数含义
-genkey生成秘钥
-alias别名
-keyalg秘钥算法
-keysize秘钥长度
-validity有效期
-keystore生成秘钥库的存储路径和名称
-keypass秘钥口令
-storepass秘钥库口令
-dnameCN:姓名;OU:组织单位名称;O:组织名称;L:省/市/自治区名称;C:国家/地区代码
2、数字证书创建
(1)服务端
keytool -genkey -alias ssl-demo-server -keyalg RSA -keysize 1024 -validity 365 -keystore ./server -dname "CN=localhost,OU=cn,O=cn,L=cn,ST=cn,C=cn" -storepass server -keypass 123456

在这里插入图片描述

(2)客户端
keytool -genkey -alias ssl-demo-client -keyalg RSA -keysize 1024 -validity 365 -keystore ./client -dname "CN=localhost,OU=cn,O=cn,L=cn,ST=cn,C=cn" -storepass client -keypass 123456

在这里插入图片描述

(3) 将服务端的证书导出来,并导入到客户端的仓库
[1] 服务端证书导出

keytool -export -alias ssl-demo-server -keystore ./server -file server.cer

在这里插入图片描述

[2] 将服务端导出证书导入到客户端仓库
keytool -export -alias ssl-demo-server -keystore ./server -file server.cer

在这里插入图片描述

[3]客户端证书导出
keytool -export -alias ssl-demo-client -keystore ./client -file client.cer

在这里插入图片描述

[4] 将客户端导出证书导入到服务端仓库
keytool -import -trustcacerts -alias ssl-demo-client -file ./client.cer -keystore E:/store/server/server

在这里插入图片描述

二、SSL单向握手通信

 SSL单向握手通信。即:客户端验证服务端的证书,服务端不验证客户端的证书。
 
 
 服务端设置:
 		/**
         * 设置是否需要验证客户端
         *  true:需要验证客户端
         *  false:不需要验证客户端
         */
        sslServerSocket.setNeedClientAuth(false);
 
1、服务端(不需要验证客户端)
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.KeyStore;
import javax.net.ServerSocketFactory;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;


public class SSLServer {

    /**
     * 服务器端证书位置
     */
    private static String SERVER_KEY_STORE = "E:\\store\\server\\server";

    /**
     * 服务器端证书密码
     */
    private static String SERVER_KEY_STORE_PASSWORD = "123456";


    /**
     * 套接字
     */
    private static Socket socket;



    public static void main(String[] args) throws Exception {

        SSLServerSocket sslServerSocket = createSSLServerSocket();

        while (true) {

            /**
             * 服务端获取连接
             */
            socket = sslServerSocket.accept();

            messageHandle();

        }

    }


    /**
     * 客户端信息处理
     */
    public static void messageHandle() {


        /**
         * 字节输入流
         */
        InputStream inputStream = null;

        /**
         * 字符输入流
         */
        InputStreamReader inputStreamReader = null;


        /**
         * 缓冲区
         */
        BufferedReader bufferedReader = null;


        /**
         * 字节输出流
         */
        OutputStream outputStream = null;

        /**
         * 文本输出流
         */
        PrintWriter printWriter = null;


        try {


            /**
             * 获取连接字节输入流
             */
            inputStream = socket.getInputStream();


            /**
             * 将输字节输入流转换为字符输入流
             */
            inputStreamReader = new InputStreamReader(inputStream);


            /**
             * 将字符输入流的数据写到缓冲区
             */
            bufferedReader = new BufferedReader(inputStreamReader);


            /**
             * 获取连接字节输出流
             */
            outputStream = socket.getOutputStream();

            /**
             * 将字节输出流转化为文本输出流
             */
            printWriter = new PrintWriter(outputStream);


            /**
             * 读取客户端发送来的数据
             */
            String data = bufferedReader.readLine();
            System.out.println("客户端消息:" + data);

            /**
             * 向客户端返回消息
             */
            printWriter.println("你好,客户端,我已经接收到你发送的消息!");

            /**
             * 刷新流
             */
            printWriter.flush();


        } catch (IOException e) {

            e.printStackTrace();

        }


    }


    /**
     * 创建SSL协议服务端Socket
     *
     * @return
     * @throws Exception
     */
    public static SSLServerSocket createSSLServerSocket() throws Exception {


        /**
         * SSL请求信托证书仓库注册
         */
        System.setProperty("javax.net.ssl.trustStore", SERVER_KEY_STORE);

        /**
         * 获取指定类型(jceks)的密钥存储库实例
         */
        KeyStore keyStore = KeyStore.getInstance("jceks");


        /**
         * 读取服务端证书
         */
        FileInputStream fileInputStream = new FileInputStream(SERVER_KEY_STORE);


        /**
         * 加载服务端证书到密钥存储库
         */
        keyStore.load(fileInputStream, null);


        /**
         * 获取密钥管理仓库实例
         */
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");


        /**
         * 初始化密钥管理仓库
         */
        keyManagerFactory.init(keyStore, SERVER_KEY_STORE_PASSWORD.toCharArray());


        /**
         *  获取协议为“TLS”的SSL上下文实例
         */
        SSLContext sslContext = SSLContext.getInstance("TLS");


        /**
         * 获取密钥管理仓库中所有的密钥管理器
         */
        KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();

        /**
         * 初始化SSL上下文
         */
        sslContext.init(keyManagers, null, null);


        /**
         * 通过SSL上下文获取ServerSocket工厂
         */
        ServerSocketFactory serverSocketFactory = sslContext.getServerSocketFactory();

        /**
         * 创建一个服务端,端口为8848
         */
        ServerSocket serverSocket = serverSocketFactory.createServerSocket(8848);

        /**
         * 服务端向下转换为SSL协议的服务端
         */
        SSLServerSocket sslServerSocket = (SSLServerSocket) serverSocket;

        /**
         * 设置是否需要客户端验证
         *  true:需要验证客户端
         *  false:不需要验证客户端
         */
        sslServerSocket.setNeedClientAuth(false);


        /**
         * 返回
         */
        return sslServerSocket;

    }


}
2、客户端
import java.io.*;
import java.net.Socket;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;

public class SSLClient {


    /**
     * 客户端证书地址
     */
    private static String CLIENT_KEY_STORE = "E:\\store\\client\\client";



    public static void main(String[] args) throws Exception {

        /**
         * SSL请求信托证书仓库注册
         */
        System.setProperty("javax.net.ssl.trustStore", CLIENT_KEY_STORE);


        /**
         *  获取Socket工厂
         */
        SocketFactory socketFactory = SSLSocketFactory.getDefault();

        /**
         * 创建Socket
         */
        Socket socket = socketFactory.createSocket("localhost", 8848);


        /**
         * 获取连接输出流
         */
        OutputStream outputStream = socket.getOutputStream();

        /**
         * 将字节输出流转化为文本输出流
         */
        PrintWriter writer = new PrintWriter(outputStream);

        /**
         * 获取连接字节输入流
         */
        InputStream inputStream = socket.getInputStream();


        /**
         * 将输字节输入流转换为字符输入流
         */
        InputStreamReader  inputStreamReader = new InputStreamReader(inputStream);


        /**
         * 将字符输入流的数据写到缓冲区
         */
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);


        /**
         * 向服务器发送信息
         */
        writer.println("你好,服务器(单向)");

        /**
         * 刷新流
         */
        writer.flush();

        /**
         * 获取服务器返回的信息
         */
        String data = bufferedReader.readLine();
        System.out.println(data);

        /**
         * 关闭连接
         */
        socket.close();

    }




}
3、运行测试

在这里插入图片描述

三、SSL双向握手通信

1、服务端
 		/**
 		 * 修改此处参数即可
         * 设置是否需要客户端验证
         *  	true:需要验证客户端
         *  	false:不需要验证客户端
         */
        sslServerSocket.setNeedClientAuth(true);
2、客户端
import java.io.*;
import java.net.Socket;
import java.security.KeyStore;
import javax.net.SocketFactory;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;

public class BothwaySSLClient {

    /**
     * 客户端证书地址
     */
    private static String CLIENT_KEY_STORE = "E:\\store\\client\\client";

    /**
     * 客户端证书密码
     */
    private static String CLIENT_KEY_STORE_PASSWORD = "123456";


    public static void main(String[] args) throws Exception {

        /**
         * SSL请求信托证书仓库注册
         */
        System.setProperty("javax.net.ssl.trustStore", CLIENT_KEY_STORE);


        /**
         * 获取连接
         */
        Socket socket = createSocket();


        /**
         * 获取连接输出流
         */
        OutputStream outputStream = socket.getOutputStream();

        /**
         * 将字节输出流转化为文本输出流
         */
        PrintWriter writer = new PrintWriter(outputStream);

        /**
         * 获取连接字节输入流
         */
        InputStream inputStream = socket.getInputStream();


        /**
         * 将输字节输入流转换为字符输入流
         */
        InputStreamReader  inputStreamReader = new InputStreamReader(inputStream);


        /**
         * 将字符输入流的数据写到缓冲区
         */
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);


        /**
         * 向服务器发送信息
         */
        writer.println("你好,服务器(双向)");

        /**
         * 刷新流
         */
        writer.flush();

        /**
         * 获取服务器返回的信息
         */
        String data = bufferedReader.readLine();
        System.out.println(data);

        /**
         * 关闭连接
         */
        socket.close();

    }



    public static Socket createSocket() throws Exception {

        /**
         * 获取指定类型(jceks)的密钥存储库实例
         */
        KeyStore keyStore = KeyStore.getInstance("jceks");

        /**
         * 读取服务端证书
         */
        FileInputStream fileInputStream = new FileInputStream(CLIENT_KEY_STORE);

        /**
         * 加载服务端证书到密钥存储库
         */
        keyStore.load(fileInputStream, null);

        /**
         * 获取密钥管理仓库实例
         */
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");

        /**
         * 初始化密钥管理仓库
         */
        keyManagerFactory.init(keyStore, CLIENT_KEY_STORE_PASSWORD.toCharArray());

        /**
         *  获取协议为“TLS”的SSL上下文实例
         */
        SSLContext sslContext = SSLContext.getInstance("TLS");

        /**
         * 获取密钥管理仓库中所有的密钥管理器
         */
        KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();

        /**
         * 初始化SSL上下文
         */
        sslContext.init(keyManagers, null, null);

        /**
         * 通过SSL上下文获取Socket工厂
         */
        SocketFactory factory = sslContext.getSocketFactory();

        /**
         * 创建Socket(连接服务器)
         */
        Socket socket = factory.createSocket("localhost", 8848);

        /**
         * 返回
         */
        return socket;
    }

}
3、运行测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8CzVirQk-1640163005301)(C:\Users\Administrator\Desktop\笔记\Java\img\无标题2.png)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大树下躲雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值