Java SSLSocket

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

1、生成证书

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

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

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

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

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

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

2、Java实现的SSL通信客户端

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上下文
SSLContext context = SSLContext.getInstance("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。

3、Java实现的SSL通信服务器端

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上下文
SSLContext context = SSLContext.getInstance("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();
}
}
}

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

客户端执行结果:

参考博客:

[1]Java使用SSLSocket通信

[2]Java实现SSL双向认证的方法

Java SSLSocket的更多相关文章

  1. Spark案例分析

    一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...

  2. java获取https网站证书,附带调用https:webservice接口

    一.java 获取https网站证书: 1.创建一个java工程,新建InstallCert类,将以下代码复制进去 package com; import java.io.BufferedReader ...

  3. JAVA错误汇总

    1.Slf4J-API版本兼容 问题描述 Exception in thread "main" java.lang.NoSuchMethodError: org.slf4j.hel ...

  4. 解决 java 使用ssl过程中出现"PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target"

    今天,封装HttpClient使用ssl时报一下错误: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorExc ...

  5. java 实现https请求

    java 实现https请求 JSSE是一个SSL和TLS的纯Java实现,通过JSSE可以很容易地编程实现对HTTPS站点的访问.但是,如果该站点的证书未经权威机构的验证,JSSE将拒绝信任该证书从 ...

  6. Java手动添加SSL证书

    出现错误为 SSLHandshakeException - unable to find valid certification path to requested target 在服务器上找到对应的 ...

  7. java socket编程开发简单例子 与 nio非阻塞通道

    基本socket编程 1.以下只是简单例子,没有用多线程处理,只能一发一收(由于scan.nextLine()线程会进入等待状态),使用时可以根据具体项目功能进行优化处理 2.以下代码使用了1.8新特 ...

  8. SSL双向认证java实现(转)

    本文通过模拟场景,介绍SSL双向认证的java实现 默认的情况下,我认为读者已经对SSL原理有一定的了解,所以文章中对SSL的原理,不做详细的介绍. 如果有这个需要,那么通过GOOGLE,可以搜索到很 ...

  9. JAVA Socket 实现HTTP与HTTPS客户端发送POST与GET方式请求

    JAVA Socket 实现HTTP与HTTPS客户端发送POST与GET方式请求 哇,一看标题怎么这么长啊,其实意思很简单,哥讨厌用HTTP Client做POST与GET提交 觉得那个毕竟是别人写 ...

随机推荐

  1. Spring事务的介绍,以及基于注解@Transactional的声明式事务

    前言 事务是一个非常重要的知识点,前面的文章已经有介绍了关于SpringAOP代理的实现过程:事务管理也是AOP的一个重要的功能. 事务的基本介绍 数据库事务特性: 原子性 一致性 隔离性 持久性 事 ...

  2. Linux ps -ef 命令输出解释

    UID: 程序拥有者PID:程序的 IDPPID:程序父级程序的 IDC:  CPU 使用的百分比STIME: 程序的启动时间TTY: 登录终端TIME : 程序使用掉 CPU 的时间CMD: 下达的 ...

  3. JavaScript正则表达式replace的一个坑

    题图来自:https://wallhaven.cc/w/md353k 经常听大家说JavaScript是魔法语言,咱却没有什么深刻体会.直到这回踩到这个坑,我终于醒悟了,JavaScript果然来自霍 ...

  4. Spring一套全通—工厂

    百知教育 - Spring系列课程 - 工厂 第一章 引言 1. EJB存在的问题 2. 什么是Spring Spring是一个轻量级的JavaEE解决方案,整合众多优秀的设计模式 轻量级 1. 对于 ...

  5. 【java+selenium3】线程休眠方法 (六)

    一.线程休眠的方法   Thread -- sleep 调用方式: Thread.sleep(long millis) 建议:不推荐使用此方式来等待,因为元素的实际渲染时间未知,长时间的等待则浪费的时 ...

  6. v-html | 数据内容包含元素标签或者样式

    问题 如果我们展示的数据包含元素标签或者样式,我们想展示标签或样式所定义的属性作用,该怎么进行渲染 插值表达式{{}}和v-text指令被直接解析为了字符串元素. <body> <d ...

  7. 学习JS的第三天

    一.逻辑分支(续) 1.三目运算符:条件运算符 a>b?c:d;表达式1?表达式2:表达式3; 根据表达式1执行的结果,来决定执行表达式2还是表达式3 表达式1结果是true执行表达式2,最终返 ...

  8. ITextRenderers html生成pdf 分页+横向

    1.pdf横向生成问题:格式化html是加上 @page{size:297mm 210mm;} public static String formatPdfHtml(String html,Strin ...

  9. CAP 5.2 版本发布通告

    前言 今天,我们很高兴宣布 CAP 发布 5.2 版本正式版,在这个版本中,我们主要致力于更好的优化使用体验以及支持新的 Transport,同时在该版本也进行了一些 bug 修复的工作. 自从 5. ...

  10. ajax的get方法获取豆瓣电影前10页的数据

    # _*_ coding : utf-8 _*_ # @Time : 2021/11/2 11:45 # @Author : 秋泊酱 # 1页数据 电影条数20 # https://movie.dou ...