用JSSE定制SSL连接http://www.yunyo ub ar.c o m/邮件群发
JSSE Java SecuritySocket Extension Java安全套接字扩展是Sun为了解决在Internet上的安全通讯而推出的解决方案。它实现了SSL和TSL传输层安全协议。在JSSE中包含了数据加密服务器验证消息完整性和客户端验证等技术。
通过使用JS SE开发人员可以在客户机和服务器之间通过T CP/IP协议安全地传输数据。这篇文章主要描述如何使用JSSE接口来控制SSL连接。
首先我通过一个简单的客户机服务器程序来介绍如何利用JSSE进行编程。当建立客户端时我们需要配置KeyStore和TrustStore文件这样在程序中我们才可以从客户端的文件系统中加载它们。然后文章将讨论授权和身份验证方面的问题。通过从KeyStore中选择不同的授权客户端程序可以连接到不同的服务器。
在运行JSSE程序前你需要正确安装JSSE。如果你安装了J2SE 1.4 JSSE已经被自动安装并配置好了如果你使用的是其他版本的Java你需要从官方站点上下载并安装JSSE安装过程这里就不再赘述。 由于JSSE是在J2SE 1.4中才成为标准的并且J2SE 1.4中的JSSE和以前的JSSE有一些细微的差别而且文中的例子都是在J2SE 1.4下调试的 因此推荐你使用J2SE 1.4运行这些例子。
在深入介绍JSSE之前让我们来一个简单的客户机服务器程序程序中包含了两个文件 S imp le S S LS erve r和S imp le S S LC lie nt。在运行程序之前你需要配置下面这些KeyStor e和Tres tStor e文件
·一个客户端的KeyStore文件该文件中包含了对Alic e和Bo b的授权。
·一个服务器端的KeyS tor e文件该文件中包含了对server的授权。
·一个名为c lientTrust的客户端TrustS tore文件该文件中包含了对server的授权。·一个名为serverTrus t的服务器端TrustSto re文件该文件中包含了对Alice和Bob的授权。
使用keytoo l可以帮助你创建这些文件该工具在Java的b in目录下
·一个客户端的KeyStore文件该文件中包含了对Alic e和Bo b的授权。
在命令窗口中输入下面的命令keytoo l-genkey-alias alice-keystore c lientKeys
窗口中会出现下面的提示根据提示输入相应的信息
输入keys tore密码 p ass word
您的名字与姓氏是什么
[Unknown] Alice
您的组织单位名称是什么
[Unknown] Development
您的组织名称是什么
[Unknown] DCQ
您所在的城市或区域名称是什么
[Unknown] ChongQ ing
您所在的州或省份名称是什么
[Unknown] ChongQ ing
该单位的两字母国家代码是什么
[Unknown] CH
CN=Alice,OU=Development,O=DCQ,L=ChongQ ing,S T=ChongQ ing,C=CH正确吗
[否] 是
输入的主密码
如果和keys tore密码相同按回车
通过相同的方式可以建立对Bob的授权。keytoo l-genkey-alias bob-keystore c lientKeys
注意在名字与姓氏一栏中填写Bob。在完成后可以键入下面的命令来检测是否已经
正确完成了授权。keytoo l-lis t-v-ke ysto re c lie ntKe ys????
·一个服务器端的KeyS tor e文件该文件中包含了对server的授权。
在命令窗口中键入下面的命令keytoo l-genkey-alias s erver-keystore serverKeys
注意将密码设为passwo rd名字与姓氏设定为Server。完成授权后同样可以通过上面提到的命令来检测。
·一个名为c lientTrust的客户端TrustS tore文件该文件中包含了对server的授权。以及一个名为serverTrus t的服务器端TrustSto re文件该文件中包含了对Alice和Bob的授权。keytool-export-alias server-keystore clientKeys -file server.cer
输入keys tore密码 p ass word
保存在文件中的认证keytoo l-export-alias alice-keystore clientKeys -file alice.cer
输入keys tore密码 p ass word
保存在文件中的认证keytoo l-export-alias bob-keystore clientKeys -file bob.cer
输入keys tore密码 p ass word
保存在文件中的认证
这样keytoo l就在当前目录下创建了三个授权文件。然后我们将serve r.cer文件导入到c lientTrust文件中将alice.cer和bob.cer导入到serverTruest文件中keytoo l-import-alias server-keystore c lientTrust -file server.cer
keytoo l-import-alia s alice-keystore serverTrust -file alice.cerkeytool-import-alias bob-keystore serverTrust-file bob.cer
到目前为止在当前目录下包含clientKeys serverKeys clientTrust serverTrust四个文件。完成了KeyStore和Trus tStore的设置后就可以运行例子程序了。首先需要运行服务器程序java-Djavax.net.ssl.keyStore=serverKeys
-Dj avax.net.s s l.ke ySto reP ass word=pa sswo rd
-Djavax.net.s s l.trustS tore#NAME?
-Djavax.net.s s l.trustS torePa sswo rd=password S imp leS S LS erver
在命令行中我们指定了keyS tore属性为s erverKe ys。 由于服务器程序需要获得客户端的授权信息我们指定trustStore为serverTrust。这样S S LS imp leServer就可以验证由S SLS imp leC lient提供的授权信息。当服务器程序成功运行后你会看到下面的提示
SimpleSSLServer running on port 49152????
这时候服务器会等待客户端发出建立连接的申请。如果你希望在另一个端口上运行服务器程序可以在命令中指定-port xxx参数其中xxx是端口号。
然后在另一个命令窗口中运行客户端程序java-Djavax.net.ss l.keyStore=c lientKeys
-Dj avax.net.s s l.ke ySto reP ass word=pa sswo rd
-Djavax.net.s s l.trustS tore=c lientTrust
-Dj avax.net.s s l.trustS torePa sswo rd=pass word S imp leS S LC lie nt
客户端程序会试图向本机的49152端口建立SSL连接。 同样你可以通过-port参数指定端口号也可以通过-host参数指定主机名称。当连接成功后会出现下面的提示信息
C onnected
同时在服务器端会提示用户客户端已经连接成功。
Simp leS S LServer
让我们先来看一下Simp leS S LServer。在main 方法中程序获得了缺省的S SLServerSocketFactory对象然后利用S S LServerSocketFactory创建一个Simp leS S LS erve r对象最后调用s tart 方法启动S imp leS S LS erve r对象。SSLServerSocketFactory ss f=
(S SLServerSocketFactory)S S LServerSocketFactory.getDefault();
SimpleSSLServer server=new SimpleSSLServer(ssf,port);server.s tart();
由于服务器是在一个单独的线程中运行的 main 方法启动了服务器之后就退出了。 s tar t 方法启动了一个新的线程该线程执行r un 方法中的代码。在r un
方法中创建了一个S SLServerSocket对象然后设定服务器需要进行客户端验证
SSLServerSocket serverSocket=
(S SLServerSocket)serverSocketFactory.createServerSocket(port);serverSocket.setNeedC lientAuth(true);
调用run 方法后程序进入了一个死循环等待客户端的连接申请。循环中的每个Socket对应一个HandshakeCo mp letedListener对象该对象是用来显示客户验证信息中的标识名称distinguished name的 。 Socket的InputStream对象被包装在一个InputDisp layer对象中这个InputDisp layer对象运行在另外一个线程中用来将Socket接收到的数据发送到S ystem.out。下面的代码是S imp leS SLServer中的主循环体while(true) {
String ident=String.valueO f(id++);
//监听连接请求.
SSLSocket socket=(SSLSocket)serverSocket.aclearcase/"target="_blank">ccept();
//通过使用HandshakeCo mp letedListener对象,程序进行授权验证.
HandshakeComp letedListener hcl=new S imp leHandshakeListener(ident);socket.addHandshakeCo mp letedListener(hc l);
InputStream in=socket.getInputStream();new InputDisplayer(ident, in);
}
程序中的Simp leHandshakeListener类实现了HandshakeComp letedListerner接口。在Simp leHandshakeListener类中实现了handshakeComp leted 方法该方法在S S L握手阶段完成后将被JSSE调用。它将显示出客户端的标识名称class S imp leHandshakeListener imp lements HandshakeComp letedListener
{
String ident;
/**
*构造函数.
*/public S impleHandshakeListener(String ident)
{this.ident=ident;
}
/**当SSL握手过程完成后该方法被激活. */public void handshakeCompleted(HandshakeCompletedEvent event)
{
//显示授权信息.try{
X509 C ertific atecert=(X509C ertificate)e ve nt.getPeerC e rtificates()[0];
String peer=cert.getSubjectDN().getName();
System.out.println(ident+":Request from"+peer);
}catch(SS LPeerUnverifiedException pue) {
System.out.println(ident+":Peer unverified");
}
}
}
用红色字体表示的两行代码是这段代码的核心 getPeerCertificates 方法返回一个X509C ertific ated对象的数组。这些X509C ertificated对象创建了客户端的身份标识。在数组中的第一个元素是客户端的验证信息而最后一个通常是CA验证。当我们有了客户端的验证信息后。我们可以得到其中的标识名称并将它传送到Sys te m.o ut。
S imp le S S LC lie nt
S imp le S S LC lie nt类比较简单但是在后面的一些比较复杂的例子中的类会继承该类。在getSLLSocketFacto ry 方法中程序返回缺省的工厂类protected S SLSocketFactory getS S LSocketFactory()throws IOException,GeneralSecurityException
{return(S SLSocketFactory)S S LSocketFactory.getDe fault();
}
在runC lie nt()方法中程序处理了输入参数后获得S S LS ockFacto ry对象调用
connect 方法连接到服务器程序。在connect 方法中程序首先创建一个S SLSocket对象然后调用S S LSocket对象的startHandshang 方法启动和服务器端的握手过程。当握手过程完成后会触发一个HandshakeCo mp letedEvent事件。在服务器端的HandshakeCo mp letedListener对象会处理这个事件。事实上JSSE可以自动启动握手过程但是必须是在第一次有数据通过Socket传输的情况下。 由于在例子程序中直到用户在键盘上输入信息后才会有数据通过Socket传输而我们希望服务器端及时报告连接情况 因此我们用startS hake 方法来手工激活握手过程。public void connect(SSLSocketFactory sf)throws IOException
{socket=(SSLSocket)sf.createSocket(host,port);try{s ocket.startHands hake();
}catch(IOException ioe) {
//握手失败.关闭连接.try{socket.close();
}catch(IOException ioe2) {
//忽略该错误.
}socket=null;throw io e;
}
}
Simp leS SLClient类中的transmit 方法也很简单。首先程序将输入流包装到一个Reader对象中然后将输出流包装到一个Writer对象中最后将数据流输出到Socketboolean done=false;
while(!done) {
String line=reader.readLine();if(line!=null) {wr iter.wr ite(lin e);wr ite r.wr ite('\n');wr iter.flu s h();
}else done=true;
}
定制KeyS tor e和TrustS tore?
还记得我们是如何运行客户端的吗我们需要在命令行中指定keySto re,ke ySto reP as word, trustS tore和trus tSto rePass word参数 以至于整个命令显得过于冗长。事实上你可以在程序中指定KeyS tor e和Trus tS tore后面的例子中将告诉你如何实现这一点。 同时在例子中还会演示如何配置多个S SLSocketFactory对象其中每个S SLS ocketFac tory对象对应不同的KeySto re和Trus tSto re设置。如果没有这种技术在同一个虚拟机上的所有安全连接都只能使用同一个K eyS to re和TrustStore。对于比较小的应用程序这也许不会产生问题但是对于那些比较大的应用程序来说这绝对是一个严重的缺陷。
在下面的例子中我们将使用Custo mTrus tStoreC lie nt来动态定义Ke yStore和Trus tStore。首先让我们先运行一下Custo mTrustS toreC lientjava CustomTrustS toreC lient
为什么运行Custo mTrus tStoreC lie nt时不需要指定KeyS tore和TrustS tore参数呢这是应为在Custo mTrus tStoreC lie nt的代码中指定了KeyS tore C lie ntKe ys和TrustStore C lientTruts以及它们的密钥password 。如果你想使用其他的KeyStore、 TrustS tore或密钥可以使用-ks、 -kspass、 -ts和-tspa ss参数来指定。下
Hostodo 算是比较小众的海外主机商,这次九月份开学季有提供促销活动。不过如果我们有熟悉的朋友应该知道,这个服务商家也是比较时间久的,而且商家推进活动比较稳,每个月都有部分活动。目前有提供机房可选斯波坎、拉斯维加斯和迈阿密。从机房的地理位置和实际的速度,中文业务速度应该不是优化直连的,但是有需要海外业务的话一般有人选择。以前一直也持有他们家的年付12美元的机器,后来用不到就取消未续约。第一、开...
ucloud云服务器怎么样?ucloud为了扩大云服务器市场份额,给出了超低价云服务器的促销活动,活动仍然是此前的Ucloud全球大促活动页面。目前,ucloud国内云服务器2元/月起;香港云服务器4元/首月;台湾云服务器3元/首月。相当于2-4元就可以试用国内、中国香港、中国台湾这三个地域的云服务器1个月了。ucloud全球大促仅限新用户,国内云服务器个人用户低至56元/年起,香港云服务器也仅8...
俄罗斯vps云服务器商家推荐!俄罗斯VPS,也叫毛子主机(毛子vps),因为俄罗斯离中国大陆比较近,所以俄罗斯VPS的延迟会比较低,国内用户也不少,例如新西伯利亚机房和莫斯科机房都是比较热门的俄罗斯机房。这里为大家整理推荐一些好用的俄罗斯VPS云服务器,这里主要推荐这三家:justhost、ruvds、justg等俄罗斯vps主机,方便大家对比购买适合自己的俄罗斯VPS。一、俄罗斯VPS介绍俄罗斯...