这个项目是基于与Ruby客户端进行通信,经过查看源代码,发现对方是经过TLS加密通信。第一次调试,尝试用serversocket与对方进行沟通,可以收到数据,但是无法获取http的包头数据,因此,将先对socket通信进行处理。 

一、根据原有软件进行沟通,可以找到原来生成的rcs-db.key、rcs-db.crt文件,可知rcs-db.crt为证书,rcs-db.key为秘钥。因为并没有任何思路来处理这两个文件,我就先打开看一看。发现秘钥的内容如下:

-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQDBajNHgexQbClBGOxJgTkevfZU4R/OmI2BZUgt3DD4RNO4cXtG
...........................................................................
-----END RSA PRIVATE KEY-----

可知使用的是RSA公钥加密算法。并且根据源码可知,是用OpenSSL加密的。开始我就根据http://blog.csdn.net/chaijunkun/article/details/7275632/这篇文章所讲将公钥和私钥都解了出来,可是并不知道怎么去使用。

然后查了一下,要通过一下步骤可以将key和certificate应用在Java里面。

安装好openssl。

首先将.key、crt文件转换成.jks文件及一对公私钥存储在新建的PKCS12 keystore中。

# Create PKCS12 keystore from private key and public certificate.
openssl pkcs12 -export -name myservercert -in selfsigned.crt -inkey server.key -out keystore.p12# Convert PKCS12 keystore into a JKS keystore
keytool -importkeystore -destkeystore mykeystore.jks -srckeystore keystore.p12 -srcstoretype pkcs12 -alias myservercert

然后可以用这个命令来查看keystore中的jks。注意这里我们将jks的别名起为myservercert。crt,p12记得加上地址。

keytool -list -v -keystore mykeystore.jks

但是要保证是自签证的证书,否则需要按此步骤顺着证书链找到可信赖的证书。

相关概念:Keytool 是一个有效的安全钥匙和证书的管理工具。Java 中的 keytool.exe (位于 JDK\Bin 目录下)可以用来创建数字证书,所有的数字证书是以一条一条(采用别名区别)的形式存入证书库的中,证书库中的一条证书包含该条证书的私钥,公钥和对应的数字证书的信息。证书库中的一条证书可以导出数字证书文件,数字证书文件只包括主体信息和对应的公钥。 Keytool 把钥匙和证书储存到一个keystore.默任的实现keystore的是一个文件.它用一个密码保护钥匙。

因为是需要双向认证的,因此我们需要生成truststore。JSSE使用Truststore和Keystore文件来提供客户端和服务器之间的安全数据传输。keytool是一个工具可以用来创建包含公钥和密钥的的keystore文件,并且利用keystore文件来创建只包含公钥的truststore文件。我们通过下面的5步简单的创建truststore和keystore文件:

生成一个含有一个私钥的keystore文件 
    验证新生成的keystor而文件 
    导出凭证文件 
    把认凭证件导入到truststore文件 
    验证新创建的truststore文件

导出凭证文件 在这一步,你可以导出自我签署凭证或是Verisign或其他的认证机构的商业凭证的。这里只说导出自我签署的凭证: 通过执行下面的命令把自我签署的凭证保存到 “selfsignedcert.cer”文件 :

keytool -export -alias certificatekey -keystore keystore.jks -rfc -file selfsignedcert.cer  

把认凭证件导入到truststore文件 执行下面的命令:

keytool -import -alias myservercert -file selfsignedcert.cer  -keystore truststore.jks  

最后验证新创建的truststore文件 执行下面的命令 :

keytool -list -v -keystore truststore.jks 

二、至此,我们已经将Truststore和Keystore全部倒入keytool中了。因为我需要解析包头。全部的代码如下:

package com.cms.listener;import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.StringTokenizer;import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManagerFactory;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;/*** Application Lifecycle Listener implementation class WorkerListener**/
public class WorkerListener implements ServletContextListener {//调用线程池ApplicationContext ctx =  new ClassPathXmlApplicationContext("config/spring/applicationContext.xml"); ThreadPoolTaskExecutor taskExecutor = (ThreadPoolTaskExecutor)ctx.getBean("taskExecutor");//定义端口号public static final int SERVER_PORT = 442;  /*** @see ServletContextListener#contextDestroyed(ServletContextEvent)*/public void contextDestroyed(ServletContextEvent arg0)  { // TODO Auto-generated method stub}/*** @see ServletContextListener#contextInitialized(ServletContextEvent)*/public void contextInitialized(ServletContextEvent arg0)  { // TODO Auto-generated method stubtry {  String serverKeyStoreFile = "c:\\Windows\\System32\\mykeystore.jks";  String serverKeyStorePwd = "changeit";  String catServerKeyPwd = "changeit";  String serverTrustKeyStoreFile = "c:\\RCS\\DB\\config\\certs\\truststore.jks";  String serverTrustKeyStorePwd = "changeit";  KeyStore serverKeyStore = KeyStore.getInstance("JKS");  serverKeyStore.load(new FileInputStream(serverKeyStoreFile), serverKeyStorePwd.toCharArray());  KeyStore serverTrustKeyStore = KeyStore.getInstance("JKS");  serverTrustKeyStore.load(new FileInputStream(serverTrustKeyStoreFile), serverTrustKeyStorePwd.toCharArray());  KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());  kmf.init(serverKeyStore, catServerKeyPwd.toCharArray());  TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());  tmf.init(serverTrustKeyStore);  SSLContext sslContext = SSLContext.getInstance("TLSv1");  //第二个参数TrustManager[] 是认证管理器,在需要双向认证时使用sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);  SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();  SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(SERVER_PORT);  //sslServerSocket.setNeedClientAuth(true);  while (true) {  SSLSocket s = (SSLSocket)sslServerSocket.accept();  Accepter accepter = new Accepter(s);accepter.service();}  } catch (Exception e) {  e.printStackTrace();  System.exit(1);  }  }class Accepter {  private SSLSocket socket;  public Accepter(SSLSocket socket) {  this.socket = socket;  System.out.println("连接到服务器的用户:" + socket);}  public void service() {  taskExecutor.execute(new Runnable() {public void run() {//这里编写处理业务代码synchronized (this) {try {  // 第一阶段: 打开输入流  InputStream is = socket.getInputStream();  System.out.println("客户端发送的请求信息: >>>>>>>>>>>>>>>>>>>>>>>>>");  // 读取第一行, 请求地址  String line = readLine(is, 0);//打印请求行  System.out.print(line);  // < Method > < URL > < HTTP Version > <\r\n>  取的是URL部分  String line2 = line;String httpversion = line2.substring(line2.length()-10).trim();httpversion = URLDecoder.decode(httpversion, "UTF-8");//反编码 URL 地址  String resource = line.substring(line.indexOf('/'), line.lastIndexOf('/') - 5);  //获得请求的资源的地址  resource = URLDecoder.decode(resource, "UTF-8");//反编码 URL 地址  String method = new StringTokenizer(line).nextElement().toString();// 获取请求方法, GET 或者 POST  int contentLength = 0;//如果为POST方法,则会有消息体长度  // 读取所有浏览器发送过来的请求参数头部信息  do {  line = readLine(is, 0);  //如果有Content-Length消息头时取出  if (line.startsWith("Content-Length")) {  contentLength = Integer.parseInt(line.split(":")[1].trim());  }  //打印请求部信息  System.out.print(line);  //如果遇到了一个单独的回车换行,则表示请求头结束  } while (!line.equals("\r\n"));  //如果是POST请求,则有请求体  if ("POST".equalsIgnoreCase(method)) {  //注,这里只是简单的处理表单提交的参数,而对于上传文件这里是不能这样处理的,  //因为上传的文件时消息体不只是一行,会有多行消息体  System.out.print(readLine(is, contentLength));  System.out.println();  }  System.out.println("客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<");  System.out.println("用户请求的资源是(uri):" + resource);  System.out.println("请求的类型是: " + method);  System.out.println("请求的http版本是: " + httpversion);  System.out.println("连接到服务器的用户:" + socket.getRemoteSocketAddress());} catch (Exception e) {  // replace with other code  e.printStackTrace();  }  }}});}  }
/*   这里我们自己模拟读取一行,因为如果使用API中的BufferedReader时,它是读取到一个回车换行后 才返回,否则如果没有读取,则一直阻塞,这就导致如果为POST请求时,表单中的元素会以消息体传送, 这时,消息体最末按标准是没有回车换行的,如果此时还使用BufferedReader来读时,则POST提交 时会阻塞。如果是POST提交时我们按照消息体的长度Content-Length来截取消息体,这样就不会阻塞 */private String readLine(InputStream is, int contentLe) throws IOException {  ArrayList lineByteList = new ArrayList();  byte readByte;  int total = 0;  if (contentLe != 0) {  do {  readByte = (byte) is.read();  lineByteList.add(Byte.valueOf(readByte));  total++;  } while (total < contentLe);//消息体读还未读完  } else {  do {  readByte = (byte) is.read();  lineByteList.add(Byte.valueOf(readByte));  } while (readByte != 10);  }  byte[] tmpByteArr = new byte[lineByteList.size()];  for (int i = 0; i < lineByteList.size(); i++) {  tmpByteArr[i] = ((Byte) lineByteList.get(i)).byteValue();  }  lineByteList.clear();  String tmpStr = new String(tmpByteArr, "UTF-8");
/*       http请求的header中有一个Referer属性,这个属性的意思就是如果当前请求是从别的页面链接过 来的,那个属性就是那个页面的url,如果请求的url是直接从浏览器地址栏输入的就没有这个值。得 到这个值可以实现很多有用的功能,例如防盗链,记录访问来源以及记住刚才访问的链接等。另外,浏 览器发送这个Referer链接时好像固定用UTF-8编码的,所以在GBK下出现乱码,我们在这里纠正一下 */if (tmpStr.startsWith("Referer")) {//如果有Referer头时,使用UTF-8编码  tmpStr = new String(tmpByteArr, "UTF-8");  }  return tmpStr;  }
}

java 通过SSL/TLS加密https建立连接相关推荐

  1. 解决Error基础连接已经关闭: 未能为SSL/TLS 安全通道建立信任关系

    今天写程序的时候调用到一个第三方的DLL文件,本机调试一切都正常,但是程序不是到服务器以后一直提示一个BUG:"基础连接已经关闭: 未能为SSL/TLS 安全通道建立信任关系".  ...

  2. C#运行出现:基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系。

    英文:The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secu ...

  3. C#Post接口报错信息:基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系--安全证书问题 解决方法

    目录 一.说明: 二.错误信息: 三.解决方法 1.引用命名空间: 2.添加接收方法(CheckValidationResult): 3.post方法里面增加调用:CheckValidationRes ...

  4. HTTPS 建立连接的详细过程

    目录 原文链接:HTTPS 建立连接的详细过程 - cccc_hi - 博客园 简介 对称加密和非对称加密 建立连接 tcp的三次挥手和四次挥手 HTTP请求过程 HTTPS 原文链接:HTTPS 建 ...

  5. 开源项目SMSS发开指南(四)——SSL/TLS加密通信详解

    本文将详细介绍如何在Java端.C++端和NodeJs端实现基于SSL/TLS的加密通信,重点分析Java端利用SocketChannel和SSLEngine从握手到数据发送/接收的完整过程.本文也涵 ...

  6. 第四篇:网络安全,SSL/TLS加密技术

    文章目录 一.前言 二.SSL/TLS 2.1 SSL/TLS是什么 2.2 SSL/TLS加密基本原理 2.3 SSL/TLS建立握手过程 三.CA & SSL Server & S ...

  7. 使用openssl进行ssl/tls加密传输会话测试

    [小蜗牛嘻哈之作] 我们首先看看下面一段"对话": [root@pps ~]# openssl s_client -connect localhost:110 -starttls ...

  8. SSL TLS HTTP HTTPS SSH 分别是什么意思?

    HTTP + SSL/TLS = HTTPS SSL(Secure Sockets Layer,安全套接字协议) TLS(Transport Layer Security,传输层安全协议) HTTP( ...

  9. https 中的SSL/TLS 加密

    其实HTTPS从最终的数据解析的角度,与HTTP没有任何的区别,HTTPS就是将HTTP协议数据包放到SSL/TSL层加密后,在TCP/IP层组成IP数据报去传输,以此保证传输数据的安全:而对于接收端 ...

最新文章

  1. day060 ajax文件上传 json补充
  2. npm nodejs包管理工具 简介
  3. linux工科软件,linux基础网络工具学习笔记
  4. java集合——遗留的集合
  5. Linux namespace概述
  6. 【体系结构】Oracle如何保证提交的数据不丢失
  7. dozer无法映射java8中的LocalDateTime类型的解决方案
  8. zabbix_get查看agent端的key值提示没有权限:Permission denied
  9. MySQL服务 - 客户端工具mysql及mysqladmin使用介绍
  10. as本地仓库更改_如何将源仓库的更改同步到fork仓库?
  11. 中巨伟业加密芯片—SMEC98SP (SE98)在产品授权生产防复制的应用方法
  12. openid与商户appid不匹配
  13. java 新浪短链接_如何通过Java调用新浪短网址官方API接口实现短网址缩短功能
  14. EDK环境搭建UEFI工程模块文件介绍
  15. WireShark黑客发现之旅(5)—扫描探测
  16. 0320-复利计算器代码
  17. phpStudy配置站点解决各种不能访问问题(本地可www.xx.com访问)
  18. 慧荣SM2246主控固态硬盘开卡一直pretest解决方法
  19. 如何开启APP2SD功能
  20. LeetCode4.python实现:寻找两个有序数组中的中位数问题☆☆☆

热门文章

  1. 淘宝获取商品详情API
  2. Choco-slover的使用
  3. 利用南十字星座测量经纬度的方法
  4. docker run --privileged参数(容器权限全开,不利于宿主机安全,宿主机容易重启)(与/usr/sbin/init共用)
  5. Web网站HTML打开QQ聊天窗口示例
  6. [Datawhale-李宏毅机器学习-39期]-005-网络设计技巧
  7. 信道建模(大尺度、小尺度、莱斯衰落、瑞利衰落、莱斯信道、瑞利信道)
  8. Centos安装traceroute
  9. 图形化编程语言的设计
  10. 第二期DBA投票“今日必看”项目分析