首页 技术 正文
技术 2022年11月8日
0 收藏 987 点赞 1,374 浏览 5015 个字

导语

要使用安全Socket需要对密码学有一定的了解。在阅读本文之前最好能阅读一下下面几个网站的内容

http://kb.cnblogs.com/page/194742/

http://kb.cnblogs.com/page/162080/

http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html

http://geek.csdn.net/news/detail/188003

创建安全客户端Socket

创建一个安全Socket很简单,首先从javax.net.ssl.SSLSocketFactory获取一个默认的工厂对象。然后通过该工厂的createSocket()方法得到一个具体的Socket对象。下面是一个简单的例子

SocketFactory factory = SSLSocketFactory.getDefault();
Socket socket = factory.createSocket("www.xdysite.cn", 7000);

代码中返回的Socket实际上是javax.net.ssl.SSLSocket,这是java.net.Socket的一个子类。不过,我们不需要了解这些细节。我们就把他当成普通的socket来使用即可,即通过其getInputStream(),getOutputStream()和其它方法加以使用。

一个简单的小案例

假设有一个接受订单的服务器在www.xdysite.cn的7000端口监听连接。每个订单使用一个TCP连接以ASCII字符串的形式发送。服务器接受订单并关闭这个连接(这里我们省略大量细节)。客户端发送的订单形式如下:

Name: liming

Product: 67x-89

Address: 1280 XiDian University

Card number: 4000-1234-5678-901

Expires: 2016/12/29

这个消息中包含了大量的信息,足以让某个监听数据包的人恶意地使用liming的信用卡号码。因此,在发送这个订单之前,应当对它加密。下面的代码将通过安全Socket发送订单:

SocketFactory factory = SSLSocketFactory.getDefault();
try {
Socket socket = factory.createSocket("www.xdysite.cn", 7000);
Writer out = new OutputStreamWriter(socket.getOutputStream(), "ASCII");
out.write("Name: liming\r\n");
out.write("Product: 67x-89\r\n");
out.write("Address: 1280 XiDian University\r\n");
out.write("Card number: 4000-1234-5678-901\r\n");
out.write("Expires: 2016/12/29\r\n");
out.flush();
} catch (IOException e) {
e.printStackTrace();
}

下面是一个HTTPS客户端的示例代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;import javax.net.SocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;public class HTTPSClient {public static void main(String[] args) {
if (args.length == 0) {
System.out.println("Usage: java HTTPSClient host");
return;
}
int port = 443;
String host = args[0];
SocketFactory factory = SSLSocketFactory.getDefault();
SSLSocket socket = null;
try {
socket = (SSLSocket) factory.createSocket(host, port);//启用所有密码组
String[] supported = socket.getSupportedCipherSuites();
socket.setEnabledCipherSuites(supported);Writer out = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");//https在GET行中需要完全URL
out.write("GET / HTTP/1.1\r\n");
out.write("Host: " + host + "\r\n\r\n");
out.flush();//读取响应
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));//读取首部
String s;
while (!(s = in.readLine()).equals("")) {
System.out.println(s);
}System.out.println();//读取长度
String contentLength = in.readLine();
int length = Integer.MAX_VALUE;
try {
length = Integer.parseInt(contentLength.trim(), 16);
} catch (NumberFormatException e) {
//这个服务器在响应体的第一行
//没有发送content-length
}
System.out.println(contentLength);int c;
int i = 0;
while ((c = in.read()) != -1 && i++ < length) {
System.out.write(c);;
}
System.out.println();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

通过上面的程序,我们可以访问类似https://www.baidu.com网站的内容。

HTTPS服务的实现

HTTPS服务器实现起来比较复杂,要创建一个安全服务器Socket,必须要完成下面的步骤:

  • 使用keytool工具生成公钥和证书
  • 花钱请可信的第三方(权威CA)认证证书
  • 为使用的加密算法创建SSLContext
  • 为使用的证书源创建一个TrustManagerFactory
  • 为使用的密钥类型创建一个KeyManagerFactory
  • 为密钥和证书数据库创建一个KeyStor对象
  • 用密钥和证书填充KeyStore对象
  • 用KeysStore及其口令短语初始化KeyManagerFactory
  • 用KeyManagerFactory中的密钥管理器(必要),TrustManagerFactory中的信任管理器和一个随机源来初始化上下文

前两步我们要么自己去做,要么找一个CA机构帮我们直接生成。为了完成测试,我们去https://www.pianyissl.com/网站获取一个免费的SSL证书。获取的是一个压缩包,解压后可以从Tomcat目录下找到keystore.jks文件通过JDK中的keytool工具可以查看证书的信息。

keytool -list -v -keystore /root/javaTest/Tomcat/keystore.jks

图片中显示的是证书的部分信息,那么接下来如何将该证书加载到服务器呢?

import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Arrays;import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;public class SSLServer {
public final static int PORT = 7000;
public final static String algorithm ="SSL";public static void main(String[] args) {
try {
SSLContext context = SSLContext.getInstance("SSL");//设置只支持X.509标准的密钥
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");//Oracle的默认密钥库类型
KeyStore ks = KeyStore.getInstance("JKS");//加载证书,在读取jks类型的证书时需要输入密码(这里是123456)
char[] password = "123456".toCharArray();
ks.load(new FileInputStream("keystore.jks"), password);
kmf.init(ks, password);
context.init(kmf.getKeyManagers(), null, null);//删除密码
Arrays.fill(password, '0');SSLServerSocketFactory factory = context.getServerSocketFactory();
SSLServerSocket server = (SSLServerSocket) factory.createServerSocket(PORT);
while(true) {
try(
Socket client = server.accept();
Writer writer = new OutputStreamWriter(client.getOutputStream());
){
writer.write("HTTP/1.1 200 OK\r\n");
writer.write("Server: SSlServer\r\n");
writer.write("Content-lenght: 10\r\n\r\n");
writer.write("hello ssl!");
}catch(IOException e){}
}} catch (NoSuchAlgorithmException | IOException
| UnrecoverableKeyException | KeyManagementException
| CertificateException| KeyStoreException e) {}
}
}

访问http://www.xdysite.cn:7000端口就可以使用SSL安全链接的HTTP了

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,487
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,903
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,736
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,487
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,127
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,289