java使用https协议访问(自签名证书,运行时指定信任库(不修改系统证书))

需求:在本地实现java的文字聊天功能。编写两个java对象,一个对象代表服务器,一个对象代表客端,一个代表客户端。客户端输入文字,服务器端接收并响应结果给客户端。

前置条件:首先生成密钥库和证书

# 生成服务器密钥库和自签名证书
keytool -genkeypair -alias server -keyalg RSA -keysize 2048 -storetype JKS -keystore server.keystore -validity 365 -storepass serverpass -keypass serverpass -dname "CN=localhost, OU=Example, O=Example, L=City, ST=State, C=US"

# 导出服务器证书
keytool -exportcert -alias server -keystore server.keystore -file server.crt -storepass serverpass

# 生成客户端信任库并导入服务器证书
keytool -importcert -alias server -file server.crt -keystore client.truststore -storepass clientpass -noprompt

服务器端口代码如下:

package com.example.demo.demos;

import javax.net.ssl.*;
import java.io.*;
import java.security.KeyStore;

public class Server {
    private static int requestCount = 0; // 计数器记录请求次数

    public static void main(String[] args) {
        try {
            // 加载服务器密钥库(包含私钥和证书)
            KeyStore keyStore = KeyStore.getInstance("JKS");
            keyStore.load(new FileInputStream("server.keystore"), "serverpass".toCharArray());

            // 创建密钥管理器工厂
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(keyStore, "serverpass".toCharArray());

            // 创建SSL上下文并初始化
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(kmf.getKeyManagers(), null, null);

            // 创建SSL服务器套接字工厂
            SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();

            // 创建SSL服务器套接字并绑定端口
            SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(8443);

            // 启用所有支持的密码套件和协议
            sslServerSocket.setEnabledCipherSuites(sslServerSocket.getSupportedCipherSuites());
            sslServerSocket.setEnabledProtocols(sslServerSocket.getSupportedProtocols());

            System.out.println("服务器已启动,等待客户端连接...");

            // 接受客户端连接
            SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();

            // 处理客户端请求
            try (BufferedReader in = new BufferedReader(new InputStreamReader(sslSocket.getInputStream()));
                 PrintWriter out = new PrintWriter(sslSocket.getOutputStream(), true)) {

                String inputLine;
                while ((inputLine = in.readLine()) != null) {
                    requestCount++; // 每次请求计数器+1
                    String response = String.format("第%d次返回结果:%s", requestCount, inputLine); // 格式化响应内容
                    System.out.println("客户端消息: " + inputLine);
                    out.println(response); // 发送格式化后的响应
                }
            }

            sslSocket.close();
            sslServerSocket.close();

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

客户端代码:

package com.example.demo.demos;

import javax.net.ssl.*;
import java.io.*;
import java.security.KeyStore;

public class Client {
    public static void main(String[] args) {
        try {
            // 加载客户端信任库(包含服务器证书)
            KeyStore trustStore = KeyStore.getInstance("JKS");
            trustStore.load(new FileInputStream("client.truststore"), "clientpass".toCharArray());

            // 创建信任管理器工厂
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
            tmf.init(trustStore);

            // 创建SSL上下文并初始化
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, tmf.getTrustManagers(), null);

            // 创建SSL套接字工厂
            SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            // 创建SSL套接字并连接到服务器
            SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket("localhost", 8443);

            // 启用所有支持的密码套件和协议
            sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());
            sslSocket.setEnabledProtocols(sslSocket.getSupportedProtocols());

            // 向服务器发送消息
            try (PrintWriter out = new PrintWriter(sslSocket.getOutputStream(), true);

                 BufferedReader in = new BufferedReader(new InputStreamReader(sslSocket.getInputStream()));
                 BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) {
                 System.out.println("请输入内容:");
                String userInput;
                while ((userInput = stdIn.readLine()) != null) {
                    out.println(userInput);
                    System.out.println("服务器返回: " + in.readLine());
                    System.out.println("请继续输入内容:");

                }
            }

            sslSocket.close();

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

关键配置说明

  1. 服务器配置

    • 使用server.keystore存储服务器私钥和证书
    • 通过KeyManagerFactory加载服务器密钥库
    • 服务器使用默认信任库验证客户端证书(如果需要双向认证)
  2. 客户端配置

    • 使用client.truststore存储信任的服务器证书
    • 通过TrustManagerFactory加载客户端信任库
    • 客户端通过SSLContext初始化自定义信任管理器

结果:客户端多次输入,服务器均正常返回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

圣诞节不感冒

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

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

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

打赏作者

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

抵扣说明:

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

余额充值