|
用 Java 2 标准版本 (J2SE) 1.4 进行 Internet 安全编程(5)
扩展 HttpServer 使其能够处理 https://URL 现在,我要们修改 HttpServer 类,使它变得安全。我希望 HTTP 服务器能处理 https://URL 请求。我在前面就提到过,JSSE 让你可以很容易的把 SSL 整合到应用中去。 创建一个服务器证书
就像我前面提到的那样,SSL 使用证书来进行验证。对于需要使用 SSL 来保证通信安全的客户端和服务器,都必须创建证书。JSSE 使用的证书要用与 J2SE 一起发布的 Java keytool 来创建。用下列命令来为 HTTP 服务器创建一个 RSA 证书。 prompt> keytool -genkey -keystore serverkeys -keyalg rsa -alias qusay 这个命令会产生一个由别名 qusay 引用的证书,并将其保存在一个名为 serverkeys 的文件中。产生证书的时候,这个工具会提示我们一些信息,如下面的信息,其中加黑的内容是我写的。 Enter keystore passWord:hellothereWhat is your first and last name?[Unknown]:ultra.domain.comWhat is the name of your organizational unit?[Unknown]:Training and ConsultingWhat is the name of your organization?[Unknown]:Javacourses.comWhat is the name of your City or Locality?[Unknown]:TorontoWhat is the name of your State or Province?[Unknown]:OntarioWhat is the two-letter country code for this unit?[Unknown]:CAIs CN=ultra, OU=Training and Consulting, O=Javacourses.com, L=Toronto, ST=Ontario, C=CA correct?[no]:yesEnter key passWord for (RETURN if same as keystore passWord):hiagain
正如你所看到的,keytool 提示为 keystore 输入密码,那是因为让服务器能访问 keystore 就必须让它知道密码。那工具也要求为别名输入一个密码。如果你愿意,这些密码信息能由 keytool 从命令行指定,使用参数 -storepass 和 -keypass 就行了。注意我使用了“ultra.domain.com”作为姓名,这个名字是为我的机器假想的一个名字。你应该输入服务器的主机名或者 IP 地址。 在你运行 keytool 命令的时候,它可能会花几秒钟的时间来产生你的密码,具体速度得看你机器的速度了。 既然我为服务器创建了证书,现在可以修改 HttpServer 使其变得安全了。如果你检查 HttpServer 类,你会注意到 getServer 方法用来返回一个服务器套接子。也就是说,只需要修改 getServer 方法让它返回一个安全的服务器套接字就可以了。在代码示例 2 中加黑的部分就是所做的改变。请注意我将端口号改成了 443,这是 https 默认的端口号。还有一点非常值得注意:0 到 1023 之间的端口号都是保留的。如果你在不同的端口运行 HttpsServer,那么 URL 应该是:https://localhost:portnumber。但如果你在 443 端口运行 HttpsServer,那么 URL 应该是:https://localhost。 示例代码 2:HttpsServer.Java import Java.io.*;import Java.net.*;import Javax.net.*;import Javax.net.ssl.*;import Java.security.*;import Java.util.StringTokenizer;/** * This class implements a multithreaded simple HTTPS * server that supports the GET request method. * It listens on port 44, waits client requests * and serves documents. */public class HttpsServer { String keystore = "serverkeys"; char keystorepass[] = "hellothere".toCharArray(); char keypassWord[] = "hiagain".toCharArray(); // The port number which the server will be listening on public static final int HTTPS_PORT = 443;public ServerSocket getServer() throws Exception {KeyStore ks = KeyStore.getInstance("JKS");ks.load(new FileInputStream(keystore), keystorepass);KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");kmf.init(ks, keypassWord);SSLContext sslcontext = SSLContext.getInstance("SSLv3");sslcontext.init(kmf.getKeyManagers(), null, null);ServerSocketFactory ssf = sslcontext.getServerSocketFactory();SSLServerSocket serversocket = (SSLServerSocket) ssf.createServerSocket(HTTPS_PORT);return serversocket; } // multi-threading -- create a new connection // for each request public void run() {ServerSocket listen;try {listen = getServer();while(true) { Socket client = listen.accept(); ProcessConnection cc = newProcessConnection(client);}} catch(Exception e) {System.out.println("Exception: "+e.getMessage());} } // main program public static void main(String argv[]) throws Exception {HttpsServer https = new HttpsServer();https.run(); }}
这几行: String keystore = "serverkeys";
|