既然 QBrowser 使用 URL 类,它就可以处理 HTTP 和 HTTPS 请求。你可以使用 HTTP 和 HTTPS 地址测试
1、请求 http://www.javacourses.com,你会看到如图 1 所示的内容。
图 1:http://www.javacourses.com 2、请求 https://www.jam.ca,结果抛出了异常。因为这个网页服务器的证书不受信任并且不能在默认页中找到,所以它抛出如图 2 所示的异常。
图 2:https://www.jam.ca 3、请求 https://localhost,这里运行着第一部分中写的 HttpServer。注意,如果你使用命令 java QBrowser 来运行 QBrowser,而服务器的证书导出后被导入默认文件 jssecacerts,那么应该将该文件拷贝到 java.home 目录的 lib/security 子目录中。如果证书被导入了其它文件,你可以使用 trustStore 选项,如:java -Djavax.net.ssl.trustStore=file QBrowser。使用其实任何一种方法,都会工作,并且你可以看到如图浏览器 3 所示的默认页面。
图 3:https://localhost HttpsURLConnection 类 这个类存在于 javax.net.ssl 包中,它扩展了 java.net.HttpURLConnection,以支持 HTTPS 描述的一些特性。它能够通过 SSL/TLS 套接字建立安全通道来请求/获取数据。示例代码 4 展示了一个小型客户端,它使用 HttpsURLConnection 类从 HTTPS 服务器下载文档。 示例代码 4:ReadHttpsURL3.java import java.io.*; import java.net.*; import javax.net.ssl.*; public class ReadHttpsURL3 { public static void main(String[] argv) throws Exception { URL url = new URL(argv[0]); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setDoOutput(true); BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while ((line = in.readLine()) != null) { System.out.println(line); } in.close(); } } 现在试试 ReadHttpsURL3,完成上面讨论的内容。注意,无论如何,既然我们使用 URL 类,你就能在命令行指定 URL,包括协议的名称。这里是一个例子: Prompt> java ReadHttpsURL3 https://www.sun.com HttpsURLConnection 有一个非常有趣的特点:一旦获得了连接,你就可以在网络连接之前使用一些有用的参数对其进行配置,如 HostnameVerifier。HostnameVerifier 是一个接口,它申明了方法:public boolean verify (String hostname, SSLSession session)。而且,它像下面所述的那样工作: l 如果 SSL/TLS 标准主机名校验逻辑失败,执行过程中会调用回调类的 verify 方法。回调类是实现了 HostnameVerifier 接口的类。 l 如果回调类检查到主机名可以接受,则允许连接,否则,连接会被终止。 回调类遵循的规则即可以是基本的验证方法,也可以依赖其它验证方法。这里说明了如何实现: public class MyVerified implements HostnameVerifier { public boolean verify(String hostname, SSLSession session) { // pop up a dialog box // ... // return either true or false } } 现在,可以这样使用它: HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setHostnameVerifier(new MyVerifier()); 信任管理器 一个 SSL 客户端,如网页浏览器,连接到 SSL 服务器 (如 HTTPS 服务器) 的时候,HTTPS 服务器将自己的证书链交给客户端验证。SSL 规范规定,如果在证书链中发现有无效的证书,客户端应该立即终止连接。一些网页浏览器,如 Netscape Communicator 和 Microsoft Internet Explorer,询问用户是否忽略无效的证书并继续检查证书链,以确定是否有可能验证通过 HTTPS 服务器。使用 javax.net.sll.TrustManager 可以很好的消除这种矛盾,它是 JSSE 信任管理器的基础接口。而这些信任管理器则是用来管理可信任的资料以及决定是否接受某个凭证的。典型的信任管理器都支持基于 X.509 的证书,它是 J2DK 的 keytool 可以管理的一个普通的证书格式。 X509TrustManager 接口 javax.net.sll.X509TrustManager 接口扩展了普通的 TrustManager 接口。使用基于 X.509 公钥证书验证方案时,信任管理器必须实现该接口。实现 X509TrustManager 可以创建信任管理器。这里有一个空实现: public class MyTrustManager implements X509TrustManager { MyTrustManager() { // constructor // create/load keystore } public void checkClientTrusted(X509Certificate chain[], String authType) throws CertificatException { } public void checkServerTrusted(X509Certificate chain[], String authType) throws CertificationException { // special handling such as poping dialog boxes } public X509Certificate[] getAcceptedIssuers() { } } 为了支持远端套接字 X.509 证书,实现了 X509TrustManager 接口的类,其实例要传递给 SSLContext 对象的 init 方法。它作为 SSL 套接字工厂。换句话说,一旦创建了信任管理器且通过 init 方法将其分配给了一个 SSLSocket,以后从 SSLContext 创建的 SocketFactories 在作信任决策时将使用新的信任管理器。下面的代码段就是个示例: X509TrustManager xtm = new MyTrustManager() TrustManager mytm[] = {xtm}; SSLContext ctx = SSLContext.getInstance("SSL"); ctx.init(null,mytm, null ); SSLSocketFactory sf = ctx.getSocketFactory(); JSSE 调试工具 Sun 的 JSSE 实现提供了动态调试跟踪支持,使用系统属性 javax.net.debug 即可。JSSE 并不正式支持这个特性,但它可以让你看到在 SSL 通信过程中幕后在干什么。这个工具可以通过如下命令使用: Prompt> java -Djavax.net.debug=option[debugSpecifiers] MySSLApp 如果你使用了 help 参数,它就会显示调试选项列表。J2SE 1.4.1 中,选项如下: all turn on all debugging ssl turn on ssl debugging The following can be used with ssl: record enable per-record tracing handshake print each handshake message keygen print key generation data session print session activity defaultctx print default SSL initialization sslctx print SSLContext tracing sessioncache print session cache tracing keymanager print key manager tracing trustmanager print trust manager tracing
handshake debugging can be widened with: data hex dump of each handshake message verbose verbose handshake message printing
record debugging can be widened with: plaintext hex dump of record plaintext 你必须指定参数 ssl 或者 all 中的一个,紧跟 debug 符号。可以使用一个或多个调试说明符,使用“:”或者“,”作为分隔符。说明符不是必须的,但可以增强可读性。这里是一些例子: Prompt> java -Djavax.net.debug=all MyApp Prompt> java -Djavax.net.debug=ssl MyApp Prompt> java -Djavax.net.debug=ssl:handshake:trustmanager MyApp 总结 这篇文章展示了如何使用 JSSE (SSL 协议的框架和实现) 开发安全的客户端应用程序。这篇文章中的例子展示了将 SSL 整合到 C/S 应用程序是多么简单的事情。这篇文章中讲到一个网页浏览器,QBrowser,可以处理 HTTP 和 HTTPS 请求。 QBrowser 中,如果服务器上,按输入 HTTPS 的地址中不存在有效的证书,则会抛出一个异常。你也许想修改 QBrowser 使其能够处理这个异常并且弹出一个窗口询问用户是否愿意下载安装证书,那么你可以把它做为一个练习。1.4.x 的 Java 插件使用了 JSSE,它有自己的的信任管理器,如果它不能在信任库里找到证书,而弹出窗口提示。 ------------------------------------------------------------------ 原文:Secure Internet Programming with Java 2, Standard Edition (J2SE) 1.4 (Part II: The Client Side) 参阅:Secure Internet Programming with Java 2, Standard Edition (J2SE) 1.4 (Part I: The Server Side) |
Internet 安全编程(信任管理器,HttpsURLConnection ...)
最新推荐文章于 2022-08-30 16:14:19 发布