Java笔记-SSLSocket双向认证实例

证书还是采用keytool生成的,这里都把信任库和私钥证书啥的,都放到了一个文件。

程序运行如下:

服务端:

客户端:

程序结构如下:

源码如下:

SslContextProvider.java

public interface SslContextProvider {

    TrustManager[] getTrustManagers() throws GeneralSecurityException, IOException;
    KeyManager[] getKeyManagers() throws GeneralSecurityException, IOException;
    String getProtocol();
}

SslUtil.java

public class SslUtil {

    private static final String JKS = "JKS";

    public static KeyManager[] createKeyManagers(String keyStorePath, String password) throws NoSuchAlgorithmException, KeyStoreException, IOException {

        return createKeyManagers(keyStorePath, password, password);
    }

    public static KeyManager[] createKeyManagers(String keyStorePath, String storePassword, String keyPassword) throws NoSuchAlgorithmException, KeyStoreException, IOException {

        String defaultAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
        KeyManagerFactory kmInstance = KeyManagerFactory.getInstance(defaultAlgorithm);

        KeyStore ksInstance = KeyStore.getInstance(JKS);
        FileInputStream fileInputStream = new FileInputStream(keyStorePath);

        try {

            ksInstance.load(fileInputStream, storePassword.toCharArray());
        }
        catch (IOException e) {

            e.printStackTrace();
        }
        catch (CertificateException e) {

            e.printStackTrace();
        }
        finally {

            if(fileInputStream != null){

                fileInputStream.close();
            }
        }

        try {

            kmInstance.init(ksInstance, keyPassword.toCharArray());

        }
        catch (UnrecoverableKeyException e) {

            e.printStackTrace();
        }

        return kmInstance.getKeyManagers();
    }

    public static SSLContext createSSLContext(SslContextProvider provider) throws GeneralSecurityException, IOException {

        SSLContext context = SSLContext.getInstance(provider.getProtocol());
        context.init(provider.getKeyManagers(), provider.getTrustManagers(), new SecureRandom());
        return context;
    }

    public static SSLServerSocket createSSLServerSocket(int port, SslContextProvider provider) throws GeneralSecurityException, IOException {

        SSLContext context = createSSLContext(provider);
        SSLServerSocketFactory serverSocketFactory = context.getServerSocketFactory();
        SSLServerSocket sslServerSocket = (SSLServerSocket) serverSocketFactory.createServerSocket(port);
        sslServerSocket.setEnabledProtocols(new String[]{provider.getProtocol()});
        sslServerSocket.setNeedClientAuth(true);
        return sslServerSocket;
    }

    public static SSLSocket createSSLSocket(String host, int port, SslContextProvider provider) throws GeneralSecurityException, IOException {

        SSLContext sslContext = createSSLContext(provider);
        SSLSocketFactory socketFactory = sslContext.getSocketFactory();
        SSLSocket sslSocket = (SSLSocket) socketFactory.createSocket(host, port);
        sslSocket.setEnabledProtocols(new String[]{provider.getProtocol()});
        return sslSocket;
    }

    public static TrustManager[] createTrustManagers(String keyStorePath, String password) throws NoSuchAlgorithmException, KeyStoreException, IOException {

        String defaultAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmInstance = TrustManagerFactory.getInstance(defaultAlgorithm);
        KeyStore ksInstance = KeyStore.getInstance(JKS);
        FileInputStream fileInputStream = new FileInputStream(keyStorePath);

        try{

            ksInstance.load(fileInputStream, password.toCharArray());
        }
        catch(IOException e){

            e.printStackTrace();
        }
        catch(CertificateException e){

            e.printStackTrace();
        }
        finally {

            if(fileInputStream != null){

                fileInputStream.close();
            }
        }

        tmInstance.init(ksInstance);
        return tmInstance.getTrustManagers();
    }

    public static String getPeerIdentity(Socket socket){

        if(!(socket instanceof SSLSocket)){

            return null;
        }

        SSLSession session = ((SSLSocket) socket).getSession();

        try {

            Principal peerPrincipal = session.getPeerPrincipal();
            return getCommonName(peerPrincipal);
        }
        catch(SSLPeerUnverifiedException e){

            e.printStackTrace();
        }

        return "unknown client";
    }

    private static String getCommonName(Principal subject){

        try{

            LdapName ldapName = new LdapName(subject.getName());
            for(Rdn rdn : ldapName.getRdns()){

                if("cn".equalsIgnoreCase(rdn.getType())){

                    return (String)rdn.getValue();
                }
            }
        }
        catch (Exception e){

            e.printStackTrace();
        }

        return null;
    }
}

SslServer.java

public class SslServer implements SslContextProvider {

    public TrustManager[] getTrustManagers() throws GeneralSecurityException, IOException {

        return SslUtil.createTrustManagers("server.jks", "cccccc");
    }

    public KeyManager[] getKeyManagers() throws GeneralSecurityException, IOException {

        return SslUtil.createKeyManagers("server.jks", "cccccc");
    }

    public String getProtocol() {

        return "TLSv1.2";
    }

    private ServerSocket createSSLSocket(int port) throws GeneralSecurityException, IOException {

        SSLServerSocket sslServerSocket = SslUtil.createSSLServerSocket(port, this);
        return sslServerSocket;
    }

    public void run(int port) throws GeneralSecurityException, IOException {

        ServerSocket serverSocket = createSSLSocket(port);
        System.out.println("服务端启动成功,等待客户端连接.... .... .... ....");

        try(SSLSocket client = (SSLSocket) serverSocket.accept(); OutputStream os = client.getOutputStream(); InputStream is = client.getInputStream()){

            System.out.println("客户端: " + SslUtil.getPeerIdentity(client) + " 成功连接!");

            int available = is.available();
            byte[] b = new byte[1024];
            is.read(b);
            System.out.println("接收到客户端消息:" + new String(b));
            System.out.println("发送消息给客户端!");
            os.write("Hello!".getBytes());
            os.flush();
            System.out.println("发送完成!");
        }
        catch (Exception e){

            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws GeneralSecurityException, IOException {

        if(args.length != 1){

            System.out.println("Usage: SslServer <port>");
            System.exit(1);
        }

        Integer port = Integer.parseInt(args[0]);
        new SslServer().run(port);
    }
}

SslClient.java

public class SslClient implements SslContextProvider {


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

        if(args.length != 2){

            System.out.println("Usage: SslClient <host> <port>");
            System.exit(1);
        }

        String host = args[0];
        Integer port = Integer.parseInt(args[1]);
        new SslClient().run(host, port);
    }

    @Override
    public TrustManager[] getTrustManagers() throws GeneralSecurityException, IOException {

        return SslUtil.createTrustManagers("client.jks", "cccccc");
    }

    @Override
    public KeyManager[] getKeyManagers() throws GeneralSecurityException, IOException {

        return SslUtil.createKeyManagers("client.jks", "cccccc");
    }

    @Override
    public String getProtocol() {

        return "TLSv1.2";
    }

    public void run(String host, Integer port) throws Exception {

        try(SSLSocket sslSocket = createSSLSocket(host, port); OutputStream os = sslSocket.getOutputStream(); InputStream is = sslSocket.getInputStream()){

            System.out.println("已成功连接到服务端.......");

            os.write("hehe".getBytes());
            os.flush();

            System.out.println("已发送 hehe 到服务端");

            byte[] buf = new byte[1024];
            is.read(buf);

            System.out.println("接收到服务端消息:" + new String(buf));
        }
        catch (Exception e){

            e.printStackTrace();
        }
    }

    private SSLSocket createSSLSocket(String host, Integer port) throws Exception {

        return SslUtil.createSSLSocket(host, port, this);
    }
}

源码打包下载地址:

https://github.com/fengfanchen/Java/tree/master/Java_Socket_Ssl_Two_Way

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

IT1995

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

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

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

打赏作者

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

抵扣说明:

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

余额充值