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. prometheus(1)之核心概念

    个人理解:prometheus核心在于 1.prom数据类型的理解 (4钟数据类型 与常用的promQL语法 其实很容易) 2.各种服务发现与正则拼接(服务发现的拼接其实官方定义好的 理解就行) 3. ...

  2. JMeter源码导入到Intellij IDEA (八)

    亲测:jmeter源码导入Intellij IDEA,导入,编译,运行! 一.环境:windows10操作系统,jdk1.8,Intellij IDEA 2018.3,jmeter5.0 下载jmet ...

  3. Java测试开发--HttpClient常规用法(九)

    1.HttpClient可以读取网页(HTTP/HTTPS)内容 2.对url发送get/post请求(带不带参数都可以),进行测试 一.maven项目pom.xml需要引入包 <depende ...

  4. 04 | 函数扩展 | es6

    函数参数的默认值 基本用法 ES6 之前,不能直接为函数的参数指定默认值,只能采用变通的方法. function log(x, y) { y = y || 'World'; console.log(x ...

  5. 浅讲.Net 6 并与之前版本写法对比

    介绍 昨天vs2022正式版已经推出了,估计很多人已经下载并开始创建.Net 6 开始尝鲜了, 本节我简要的给大家介绍一下.Net 6的一些改动. 正文 本次.Net6带来最明显的变化就是: 采用顶级 ...

  6. 第一天 python入门 基础 “”“Hello World”和if-elif的使用、数据类型

    (1)第一个程序"""Hello World" 实现python环境打印输出:Hello World 程序: print("Hello World&q ...

  7. 【JavaScript实用技巧(二)】Js操作DOM(由问题引发的文章改版,新人大佬都可)

    [JavaScript实用技巧(二)]Js操作DOM(由问题引发的文章改版,新人大佬都可!) 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人 ...

  8. Part 38 AngularJS cancel route change

    n this video we will discuss, how to cancel route change in Angular with an example. This is extreme ...

  9. Python如何格式化输出

    目录 Python中的格式化输出 1.旧格式化 2.新格式format( ) 函数 Python中的格式化输出 格式化输出就是将字符串中的某些内容替换掉再输出就是格式化输出 旧格式化输出常用的有%d( ...

  10. scrapy获取58同城数据

    1. scrapy项目的结构 项目名字 项目名字 spiders文件夹 (存储的是爬虫文件) init 自定义的爬虫文件 核心功能文件 **************** init items 定义数据 ...