javascript

位置:IT落伍者 >> javascript >> 浏览文章

用JSSE定制SSL连接


发布日期:2022年06月19日
 
用JSSE定制SSL连接

JSSE(Java Security Socket ExtensionJava安全套接字扩展)是Sun为了解决在Internet上的安全通讯而推出的解决方案它实现了SSL和TSL(传输层安全)协议在JSSE中包含了数据加密服务器验证消息完整性和客户端验证等技术通过使用JSSE开发人员可以在客户机和服务器之间通过TCP/IP协议安全地传输数据这篇文章主要描述如何使用JSSE接口来控制SSL连接

首先我通过一个简单的客户机/服务器程序来介绍如何利用JSSE进行编程当建立客户端时我们需要配置KeyStore和TrustStore文件这样在程序中我们才可以从客户端的文件系统中加载它们然后文章将讨论授权和身份验证方面的问题通过从KeyStore中选择不同的授权客户端程序可以连接到不同的服务器

运行例子程序

下载例子程序

在运行JSSE程序前你需要正确安装JSSE如果你安装了JSE JSSE已经被自动安装并配置好了如果你使用的是其他版本的Java你需要从官方站点上下载并安装JSSE安装过程这里就不再赘述由于JSSE是在JSE 中才成为标准的并且JSE 中的JSSE和以前的JSSE有一些细微的差别而且文中的例子都是在JSE 下调试的因此推荐你使用JSE 运行这些例子

在深入介绍JSSE之前让我们来一个简单的客户机/服务器程序程序中包含了两个文件SimpleSSLServer和SimpleSSLClient在运行程序之前你需要配置下面这些KeyStore和TrestStore文件

· 一个客户端的KeyStore文件该文件中包含了对Alice和Bob的授权

· 一个服务器端的KeyStore文件该文件中包含了对server的授权

· 一个名为clientTrust的客户端TrustStore文件该文件中包含了对server的授权

· 一个名为serverTrust的服务器端TrustStore文件该文件中包含了对Alice和Bob的授权

使用keytool可以帮助你创建这些文件(该工具在Java的bin目录下)

· 一个客户端的KeyStore文件该文件中包含了对Alice和Bob的授权

在命令窗口中输入下面的命令

keytool genkey alias alice keystore clientKeys

窗口中会出现下面的提示根据提示输入相应的信息

输入keystore密码  password

您的名字与姓氏是什么?

  [Unknown]  Alice

您的组织单位名称是什么?

  [Unknown]  Development

您的组织名称是什么?

  [Unknown]  DCQ

您所在的城市或区域名称是什么?

  [Unknown]  ChongQing

您所在的州或省份名称是什么?

  [Unknown]  ChongQing

该单位的两字母国家代码是什么

  [Unknown]  CH

CN=Alice OU=Development O=DCQ L=ChongQing ST=ChongQing C=CH 正确吗?

  [否]  是

输入的主密码

(如果和 keystore 密码相同按回车)

通过相同的方式可以建立对Bob的授权

keytool genkey alias bob keystore clientKeys

注意在名字与姓氏一栏中填写Bob在完成后可以键入下面的命令来检测是否已经正确完成了授权

keytool list v keystore clientKeys

· 一个服务器端的KeyStore文件该文件中包含了对server的授权

在命令窗口中键入下面的命令

keytool genkey alias server keystore serverKeys

注意将密码设为password名字与姓氏设定为Server完成授权后同样可以通过上面提到的命令来检测

· 一个名为clientTrust的客户端TrustStore文件该文件中包含了对server的授权以及一个名为serverTrust的服务器端TrustStore文件该文件中包含了对Alice和Bob的授权

keytool export alias server keystore clientKeys file servercer

输入keystore密码  password

保存在文件中的认证

keytool export alias alice keystore clientKeys file alicecer

输入keystore密码  password

保存在文件中的认证

keytool export alias bob keystore clientKeys file bobcer

输入keystore密码  password

保存在文件中的认证

这样keytool就在当前目录下创建了三个授权文件然后我们将servercer文件导入到clientTrust文件中将alicecer和bobcer导入到serverTruest文件中

keytool import alias server keystore clientTrust file servercer

keytool import alias alice keystore serverTrust file alicecer

keytool import alias bob keystore serverTrust file bobcer

到目前为止在当前目录下包含clientKeysserverKeysclientTrustserverTrust四个文件完成了KeyStore和TrustStore的设置后就可以运行例子程序了首先需要运行服务器程序

java sslkeyStore=serverKeys

      sslkeyStorePassword=password

      ssltrustStore=serverTrust

  ssltrustStorePassword=password SimpleSSLServer

在命令行中我们指定了keyStore属性为serverKeys由于服务器程序需要获得客户端的授权信息我们指定trustStore为serverTrust这样SSLSimpleServer就可以验证由SSLSimpleClient提供的授权信息当服务器程序成功运行后你会看到下面的提示

SimpleSSLServer running on port

这时候服务器会等待客户端发出建立连接的申请如果你希望在另一个端口上运行服务器程序可以在命令中指定port xxx参数其中xxx是端口号

然后在另一个命令窗口中运行客户端程序

java sslkeyStore=clientKeys

  sslkeyStorePassword=password

  ssltrustStore=clientTrust

  ssltrustStorePassword=password SimpleSSLClient

客户端程序会试图向本机的端口建立SSL连接同样你可以通过port参数指定端口号也可以通过host参数指定主机名称当连接成功后会出现下面的提示信息

Connected

同时在服务器端会提示用户客户端已经连接成功

SimpleSSLServer

让我们先来看一下SimpleSSLServer在main()方法中程序获得了缺省的SSLServerSocketFactory对象然后利用SSLServerSocketFactory创建一个SimpleSSLServer对象最后调用start()方法启动SimpleSSLServer对象

SSLServerSocketFactory ssf=      

(SSLServerSocketFactory)SSLServerSocketFactorygetDefault();

SimpleSSLServer server=new SimpleSSLServer(ssf port);

serverstart();

由于服务器是在一个单独的线程中运行的main()方法启动了服务器之后就退出了start()方法启动了一个新的线程该线程执行run()方法中的代码在run()方法中创建了一个SSLServerSocket对象然后设定服务器需要进行客户端验证

SSLServerSocket serverSocket=  (SSLServerSocket)serverSocketFactorycreateServerSocket(port);

serverSocketsetNeedClientAuth(true);

调用run()方法后程序进入了一个死循环等待客户端的连接申请循环中的每个Socket对应一个HandshakeCompletedListener对象(该对象是用来显示客户验证信息中的标识名称[distinguished name]的)Socket的InputStream对象被包装在一个InputDisplayer对象中这个InputDisplayer对象运行在另外一个线程中用来将Socket接收到的数据发送到Systemout下面的代码是SimpleSSLServer中的主循环体

while (true) {

       String ident=StringvalueOf(id++);

       //监听连接请求

       SSLSocket socket=(SSLSocket)serverSocketaccept();

       //通过使用HandshakeCompletedListener对象程序进行授权验证

       HandshakeCompletedListener hcl=new SimpleHandshakeListener(ident);

       socketaddHandshakeCompletedListener(hcl);

       InputStream in=socketgetInputStream();

       new InputDisplayer(ident in);

}

程序中的SimpleHandshakeListener类实现了HandshakeCompletedListerner接口在SimpleHandshakeListener类中实现了handshakeCompleted()方法该方法在SSL握手阶段完成后将被JSSE调用它将显示出客户端的标识名称

class SimpleHandshakeListener implements HandshakeCompletedListener

{

  String ident;

      /**

       * 构造函数

       */

      public SimpleHandshakeListener(String ident)

      {

        thisident=ident;

      }

      /**当SSL握手过程完成后该方法被激活 */

      public void handshakeCompleted(HandshakeCompletedEvent event)

      {

        //显示授权信息

        try {

          XCertificate

            cert=(XCertificate)eventgetPeerCertificates()[];

          String peer=certgetSubjectDN()getName();

          Systemoutprintln(ident+: Request from +peer);

        }

        catch (SSLPeerUnverifiedException pue) {

          Systemoutprintln(ident+: Peer               

上一篇:Flash、HTML、Ajax 谁将赢得Web应用之战

下一篇:JS的IE和Firefox兼容性汇编