网络编程三:SSLSocket通信

来源:互联网 发布:mac磁盘工具找不到硬盘 编辑:程序博客网 时间:2024/06/18 11:10

JSSE(Java Security Socket Extension)是Sun公司为了解决互联网信息安全传输提出的一个解决方案,它实现了SSL和TSL协议,包含了数据加密、服务器验证、消息完整性和客户端验证等技术。通过使用JSSE简洁的API,可以在客户端和服务器端之间通过SSL/TSL协议安全地传输数据。
———《大型分布式网站架构设计与实践》的第3.5.2章节——SSL/TLS

简单来说SSLSocket通信就是需要服务端和客户端进行证书验证的socket通信


服务端:

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.net.Socket;import java.security.KeyStore;import javax.net.ssl.KeyManagerFactory;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLServerSocket;import javax.net.ssl.TrustManagerFactory;public class SSLServer {    private SSLServerSocket sslServerSocket;    //服务端将要使用到server.keystore和root.keystore    public void init() throws Exception {        int port = 2016;        String keystorePath = "D:/file/certificate/server.keystore";        String trustKeystorePath = "D:/file/certificate/root.keystore";        String keystorePassword = "11111qqqqq";        SSLContext context = SSLContext.getInstance("SSL");        //服务端证书库        KeyStore keystore = KeyStore.getInstance("pkcs12");        FileInputStream keystoreFis = new FileInputStream(keystorePath);        keystore.load(keystoreFis, keystorePassword.toCharArray());        //信任证书库        KeyStore trustKeystore = KeyStore.getInstance("jks");        FileInputStream trustKeystoreFis = new FileInputStream(trustKeystorePath);        trustKeystore.load(trustKeystoreFis, keystorePassword.toCharArray());        //密钥库        KeyManagerFactory kmf = KeyManagerFactory.getInstance("sunx509");        kmf.init(keystore, keystorePassword.toCharArray());        //信任库        TrustManagerFactory tmf = TrustManagerFactory.getInstance("sunx509");        tmf.init(trustKeystore);        //初始化SSL上下文        context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);        //初始化SSLSocket        sslServerSocket = (SSLServerSocket)context.getServerSocketFactory().createServerSocket(port);        //设置这个SSLServerSocket需要授权的客户端访问        sslServerSocket.setNeedClientAuth(true);    }//init finish    public void process(String feedbackdata) throws Exception {        while(true) {            //接收客户端发来的数据            Socket socket = sslServerSocket.accept();            BufferedReader reader = null;            reader = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));            try {                while (true){                    //输出得到的数据                    System.out.println("Info from client: " + reader.readLine());                }            }catch (Exception e){                System.out.println("Client is offline.");            }finally {                try {                    if (reader != null){                        reader.close();                    }                }catch (IOException e){                    e.printStackTrace();                }            }//receive finish            //向客户端发送反馈数据            OutputStreamWriter outSW = null;            BufferedWriter bw = null;            try {                outSW = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");                  bw = new BufferedWriter(outSW);                bw.write(feedbackdata);                bw.flush();            }catch (Exception e){                e.printStackTrace();            }finally {                  try {                    if (bw != null){                        bw.close();                    }                    if (outSW != null){                        outSW.close();                    }                    if (socket != null){                        socket.close();                    }                }catch (IOException e){                    e.printStackTrace();                }            }//feedback finish         }//while finish    }//process finish    public static void main(String[] args) throws Exception {        SSLServer server = new SSLServer();        server.init();        System.out.println("Server Client");        //输入需要传输的数据到feedbackString        String feedbackString = "AAAAAAAAAA";        server.process(feedbackString);    }}

客户端:

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.security.KeyStore;import javax.net.ssl.KeyManagerFactory;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLSocket;import javax.net.ssl.TrustManagerFactory;public class SSLClient {    private SSLSocket sslSocket;    //客户端将要使用到client.keystore和root.keystore    public void init() throws Exception {        String host = "127.0.0.1";        int port = 2016;        String keystorePath = "D:/file/certificate/client.keystore";        String trustKeystorePath = "D:/file/certificate/root.keystore";        String keystorePassword = "22222wwwww";        SSLContext context = SSLContext.getInstance("SSL");//这里可以是:SSL、TLS、TLSv1、TLSv1.2等        //客户端证书库        KeyStore clientKeystore = KeyStore.getInstance("pkcs12");        FileInputStream keystoreFis = new FileInputStream(keystorePath);        clientKeystore.load(keystoreFis, keystorePassword.toCharArray());        //信任证书库        KeyStore trustKeystore = KeyStore.getInstance("jks");        FileInputStream trustKeystoreFis = new FileInputStream(trustKeystorePath);        trustKeystore.load(trustKeystoreFis, keystorePassword.toCharArray());        //密钥库        KeyManagerFactory kmf = KeyManagerFactory.getInstance("sunx509");        kmf.init(clientKeystore, keystorePassword.toCharArray());        //信任库        TrustManagerFactory tmf = TrustManagerFactory.getInstance("sunx509");        tmf.init(trustKeystore);        //初始化SSL上下文        context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);        sslSocket = (SSLSocket)context.getSocketFactory().createSocket(host, port);    }//init finish    //写入要传给服务端的数据 和 接收服务端返回的数据    public void InputYourData(String data) throws Exception {        //往SSLSocket中写入数据        OutputStreamWriter outSW = null;        BufferedWriter bw = null;        try{        outSW = new OutputStreamWriter(sslSocket.getOutputStream(), "UTF-8");          bw = new BufferedWriter(outSW);        bw.write(data);        bw.flush();        }catch (Exception e) {            e.printStackTrace();        }finally{            if (bw != null){                bw.close();            }            if (outSW != null){                outSW.close();            }        }        //从SSLSocket中读取数据        BufferedReader reader = null;        reader = new BufferedReader(new InputStreamReader(sslSocket.getInputStream(),"UTF-8"));        try {            while (true){                //输出得到的数据                System.out.println("Info from server: " + reader.readLine());            }        }catch (Exception e){            System.out.println("server bad "+e);        }finally {            try {                if (reader != null){                    reader.close();                }                if (sslSocket != null){                    sslSocket.close();                }            }catch (IOException e){                e.printStackTrace();            }        }    }//InputYourData finish    public static void main(String[] args) throws Exception {        SSLClient client = new SSLClient();        client.init();        System.out.println("Socket Client");        //输入需要传输的数据到dataString        String dataString = "XXXXXXXXXXX";        client.InputYourData(dataString);    }}

注意事项:
一、启动顺序要先启动服务端,后启动客户端
二、SSLSocket通信比普通的Socket通信多了个验证证书的部分(即init()方法)
三、服务端和客户端的init()方法基本一样,主要区别在于:

客户端需要:

  • 访问的目标地址
  • 目标地址的端口号
  • 客户端证书
  • 客户端证书密码

服务端需要:

  • 只需要定义端口号
  • 服务端证书
  • 服务端证书密码
0 0