SSLSocket

作者: shysh95 | 来源:发表于2018-07-01 20:22 被阅读0次

    SSLSocket定义

    SSLSocket扩展Socket并提供使用SSL或TLS协议的安全套接字。它也是基于正常的流套接字,但是在网络传输协议(如TCP)上添加了安全保护层。

    SSLSocket相关类

    功能描述
    SSLContext 该类的实例表示安全套接字协议的实现,是SSLSocketFactory、SSLServerSocketFactory和SSLEngine的工厂
    SSLSocket 扩展自Socket
    SSLServerSocket 扩展自ServerSocket
    SSLSocketFactory 抽象类,扩展自SocketFactory,是SSLSocket的工厂
    SSLServerSocketFactory 抽象类,扩展自ServerSocketFactory,是SSLServerSocket的工厂
    KeysStore 密钥和证书的存储设施
    KeyManager 接口,Java Secure Socket Extension密钥管理器
    TrustManger 接口,信任管理器
    X509TrustedManager TrustManger的子接口,管理X509证书,验证远程安全套接字

    SSLServerSocket实现

    SSLServerSocket需要证书进行安全全验证

    使用keytool工具生成一个名称为seckey证书

    $ keytool -genkey -keystore seckey -keyalg rsa -alias SSL
    

    服务端编码

    package cn.sh.sslsocket.server;
    
    import javax.net.ssl.*;
    import java.io.*;
    import java.net.Socket;
    import java.security.*;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    
    /**
     * @author sh
     */
    public class SSLSocketServer {
    
        public static void main(String[] args) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {
            //准备KeyStore相关信息
            String keyName = "SSL";
            String keyStoreName = "/Users/sh/workspace/netty-demo/src/cn/sh/sslsocket/seckey";
            char[] keyStorePwd = "123456".toCharArray();
            char[] keyPwd = "1234567890".toCharArray();
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    
            //装载生成的seckey
            try(InputStream in = new FileInputStream(new File(keyStoreName))) {
                keyStore.load(in, keyStorePwd);
            }
    
            //初始化KeyManagerFactory
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(keyStore, keyPwd);
    
            //初始化SSLContext
            SSLContext context = SSLContext.getInstance(keyName);
            context.init(kmf.getKeyManagers(), new TrustManager[]{getX509TrustManger()}, new SecureRandom());
    
            //监听和接受客户端连接
            SSLServerSocketFactory factory = context.getServerSocketFactory();
            SSLServerSocket serverSocket = (SSLServerSocket) factory.createServerSocket(10002);
            System.out.println("服务器端已启动!!!");
            //等待客户端连接
            Socket client = serverSocket.accept();
            System.out.println("客户端地址:" + client.getRemoteSocketAddress());
            //准备输出流,用于向客户端发送信息
            OutputStream output = client.getOutputStream();
            //获取输入流,用于读取客户端发送的信息
            InputStream in = client.getInputStream();
            byte[] buf = new byte[1024];
            int len;
            if ((len = in.read(buf)) != -1) {
                output.write(buf, 0, len);
            }
            //冲刷数据
            output.flush();
            //关闭输入输出流
            output.close();
            in.close();
            serverSocket.close();
        }
    
    
        public static X509TrustManager getX509TrustManger() {
            return new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    
                }
    
                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    
                }
    
                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
            };
        }
    
    }
    

    客户端实现

    普通Socket连接服务器

    实现

    package cn.sh.sslsocket.client;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    
    /**
     * @author sh
     */
    public class SocketClient {
    
        public static void main(String[] args) throws IOException {
            Socket socket = new Socket("localhost", 10002);
            OutputStream output = socket.getOutputStream();
            InputStream input = socket.getInputStream();
            output.write("I am SocketClient".getBytes());
            output.flush();
            byte[] buf = new byte[1024];
            int len;
            StringBuilder builder = new StringBuilder();
            while ((len = input.read(buf)) != -1) {
                builder.append(new String(buf, 0, len));
            }
            System.out.println("client received:" + builder.toString());
        }
    }
    

    运行结果

    服务器结果如下图

    运行结果

    服务端会抛出异常javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?

    客户端结果如下图

    运行结果

    客户端接收到乱码

    使用SSLSocket,不使用证书

    编码实现

    package cn.sh.sslsocket.client;
    
    import javax.net.ssl.SSLSocket;
    import javax.net.ssl.SSLSocketFactory;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    /**
     * @author sh
     */
    public class NoUseKeySSLSocketClient {
    
        public static void main(String[] args) throws IOException {
            SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
            SSLSocket sslSocket = (SSLSocket) factory.createSocket("localhost", 10002);
            OutputStream output = sslSocket.getOutputStream();
            InputStream input = sslSocket.getInputStream();
            output.write("I am NoUseKeySSLSocketClient".getBytes());
            output.flush();
            byte[] buf = new byte[1024];
            int len;
            StringBuilder builder = new StringBuilder();
            while ((len = input.read(buf)) != -1) {
                builder.append(new String(buf, 0, len));
            }
            System.out.println("client received:" + builder.toString());
        }
    }
    

    运行结果

    服务器结果如下图

    运行结果

    服务端会抛出异常javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown

    客户端结果如下图

    运行结果

    客户端会抛出异常sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

    使用SSLSocket,并且使用证书

    编码实现

    package cn.sh.sslsocket.client;
    
    import cn.sh.sslsocket.server.SSLSocketServer;
    
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSocket;
    import javax.net.ssl.SSLSocketFactory;
    import javax.net.ssl.TrustManager;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    import java.security.KeyManagementException;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    
    /**
     * @author sh
     */
    public class SSLSocketClient {
    
        public static void main(String[] args) throws NoSuchAlgorithmException, KeyManagementException, IOException {
            SSLContext context = SSLContext.getInstance("SSL");
            context.init(null, new TrustManager[]{SSLSocketServer.getX509TrustManger()}, new SecureRandom());
            SSLSocketFactory factory = context.getSocketFactory();
    
            SSLSocket sslSocket = (SSLSocket) factory.createSocket("localhost", 10002);
            OutputStream output = sslSocket.getOutputStream();
            InputStream input = sslSocket.getInputStream();
            output.write("I am SSLSocketClient".getBytes());
            output.flush();
            byte[] buf = new byte[1024];
            int len;
            StringBuilder builder = new StringBuilder();
            while ((len = input.read(buf)) != -1) {
                builder.append(new String(buf, 0, len));
            }
            output.close();
            System.out.println("client received:" + builder.toString());
        }
    }
    

    运行结果

    服务器结果如下图

    运行结果

    客户端结果如下图

    运行结果

    代码地址

    代码地址

    本文章的代码在cn.sh.sslsocket包中!

    相关文章

      网友评论

          本文标题:SSLSocket

          本文链接:https://www.haomeiwen.com/subject/xzshuftx.html