Java使用SSLSocket通信

简介:
+关注继续查看

JSSE(Java Security Socket Extension)是Sun公司为了解决互联网信息安全传输提出的一个解决方案,它实现了SSL和TSL协议,包含了数据加密、服务器验证、消息完整性和客户端验证等技术。通过使用JSSE简洁的API,可以在客户端和服务器端之间通过SSL/TSL协议安全地传输数据。

首先,需要将OpenSSL生成根证书CA及签发子证书一文中生成的客户端及服务端私钥和数字证书进行导出,生成Java环境可用的keystore文件。

客户端私钥与证书的导出:

1
2
openssl pkcs12 -export -clcerts -name www.mydomain.com \
-inkey private/client-key.pem -in certs/client.cer -out certs/client.keystore

191952_1nzY_1434710.png

服务器端私钥与证书的导出:

1
2
openssl pkcs12 -export -clcerts -name www.mydomain.com \
-inkey private/server-key.pem -in certs/server.cer -out certs/server.keystore

192440_poCJ_1434710.png

受信任的CA证书的导出:

1
2
keytool -importcert -trustcacerts -alias www.mydomain.com -file certs/ca.cer \
-keystore certs/ca-trust.keystore

200735_n3mV_1434710.png

之后,便会在certs文件夹下生成ca-trust.keystore文件。加上上面生成的server.keystore和client.keystore,certs下会生成这三个文件:

201315_VnzM_1434710.png

Java实现的SSL通信客户端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.demo.ssl;
 
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
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;
    public static void main(String[] args) throws Exception {
        SSLClient client = new SSLClient();
        client.init();
        System.out.println("SSLClient initialized.");
        client.process();
    }
     
    //客户端将要使用到client.keystore和ca-trust.keystore
    public void init() throws Exception {
        String host = "127.0.0.1";
        int port = 1234;
        String keystorePath = "/home/user/CA/certs/client.keystore";
        String trustKeystorePath = "/home/user/CA/certs/ca-trust.keystore";
        String keystorePassword = "abc123_";
        SSLContext context = SSLContext.getInstance("SSL");
        //客户端证书库
        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);
    }
     
    public void process() throws Exception {
        //往SSLSocket中写入数据
        String hello = "hello boy!";
        OutputStream out = sslSocket.getOutputStream();
        out.write(hello.getBytes(), 0, hello.getBytes().length);
        out.flush();
         
        //从SSLSocket中读取数据
        InputStream in = sslSocket.getInputStream();
        byte[] buffer = new byte[50];
        in.read(buffer);
        System.out.println(new String(buffer));
    }
}

初始化时,首先取得SSLContext、KeyManagerFactory、TrustManagerFactory实例,然后加载客户端的密钥库和信任库到相应的KeyStore,对KeyManagerFactory和TrustManagerFactory进行初始化,最后用KeyManagerFactory和TrustManagerFactory对SSLContext进行初始化,并创建SSLSocket。

Java实现的SSL通信服务器端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package com.demo.ssl;
 
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
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;
    public static void main(String[] args) throws Exception {
        SSLServer server = new SSLServer();
        server.init();
        System.out.println("SSLServer initialized.");
        server.process();
    }
     
    //服务器端将要使用到server.keystore和ca-trust.keystore
    public void init() throws Exception {
        int port = 1234;
        String keystorePath = "/home/user/CA/certs/server.keystore";
        String trustKeystorePath = "/home/user/CA/certs/ca-trust.keystore";
        String keystorePassword = "abc123_";
        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);
    }
     
    public void process() throws Exception {
        String bye = "Bye!";
        byte[] buffer = new byte[50];
        while(true) {
            Socket socket = sslServerSocket.accept();
            InputStream in = socket.getInputStream();
            in.read(buffer);
            System.out.println("Received: " new String(buffer));
            OutputStream out = socket.getOutputStream();
            out.write(bye.getBytes());
            out.flush();
        }
    }
}

先运行服务器端,再运行客户端。服务器端执行结果:

200138_0HVg_1434710.png

客户端执行结果:

201752_YeZK_1434710.png

目录
相关文章
|
2天前
|
网络协议 Java
Java TCP通信详解
TCP(Transmission Control Protocol)是一种面向连接的、可靠的网络传输协议,它提供了端到端的数据传输和可靠性保证。TCP通信适用于对数据传输的可靠性和完整性要求较高的场景,如文件传输、网页浏览等。本文将详细介绍Java中如何使用TCP协议进行网络通信,包括TCP套接字、服务器和客户端的创建、数据传输等。
20 0
|
2天前
|
网络协议 Java
Java UDP通信详解
UDP(User Datagram Protocol)是一种无连接的网络传输协议,它不像TCP那样需要建立连接和维护状态,因此更加轻量级。UDP适用于那些对数据传输的实时性要求较高,可以容忍一定数据丢失的场景。本文将详细介绍Java中如何使用UDP协议进行网络通信,包括UDP套接字、数据传输、服务器和客户端的创建等。
29 0
|
4天前
|
Java
Java的Socket进行通信
下面是一个使用Java的Socket进行通信的简单示例
|
23天前
|
网络协议 Java
Java通信程序TCP
Java通信程序TCP
13 0
|
23天前
|
网络协议 Java
Java通信程序UDP
Java通信程序UDP
15 0
|
1月前
|
缓存 Dubbo Java
Java面试题顶级理解!Dubbo注册中心挂了,服务还可以继续通信吗?
什么情况?一位工作了 5 年的 Java 程序员,竟然回答不出这个问题?说“Dubbo注册中心挂了, 服务之间还可以继续通信吗”?今天,我话2分钟时间给大家来聊一聊。
54 0
|
2月前
|
缓存 Java 测试技术
探索Java RESTful中的GET请求:资源的获取与无状态通信
在现代Web应用开发中,HTTP的GET请求是一种常见而重要的通信方式。它是RESTful架构中的核心操作之一,用于获取资源的信息。本文将带您深入了解Java中使用GET请求来构建RESTful API,探讨其特点、实现方式、用例以及在实际应用中的优势。
|
2月前
|
网络协议 Java
Java实现TCP通信的文件上传 之 代码优化开启多线程
Java实现TCP通信的文件上传 之 代码优化开启多线程
|
2月前
|
网络协议 Java
Java实现TCP通信的文件上传
Java实现TCP通信的文件上传
|
2月前
|
网络协议 Java
java实现服务器与客户端之间的TCP通信
java实现服务器与客户端之间的TCP通信
推荐文章
更多