单向验证,客户机只验证服务器的证书,服务器不验证客户机的证书。所以只需要生成服务器端的keystore.
1. 以jks格式生成服务器端包含Public key和Private Key的keystore文件,keypass与storepass务必要一样,因为在tomcat server.xml中只配置一个password. keytool -genkey -alias server -keystore serverKeystore.jks -keypass 123456 -storepass 123456 -keyalg RSA -keysize 512 -validity 365 -v -dname "CN = W03GCA01A,O = ABC BANK,DC = Server Https,DC = ABC,OU = Firefly Technology And Operation" 2. 从keystore中导出别名为server的服务端证书. keytool -export -alias server -keystore serverKeystore.jks -storepass 123456 -file server.cer 3. 将server.cer导入客户端的信任证书库clientTruststore.jks。 keytool -import -alias trustServer -file server.cer -keystore clientTruststore.jks -storepass 123456 服务器端: serverKeystore.jks 客户端: clientTruststore.jks 4. 在tomcat 配置server.xmlXml代码
-
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
-
maxThreads="150" scheme="https" secure="true"
-
clientAuth="false" sslProtocol="TLS"
-
keystoreFile="keystore/serverKeystore.jks" keystorePass="123456" />
5. 客户端代码
Java代码
-
/**
-
*
-
*/
-
package com.ssl.http;
-
-
import java.io.File;
-
import java.io.FileInputStream;
-
import java.security.KeyStore;
-
-
import org.apache.http.HttpEntity;
-
import org.apache.http.HttpResponse;
-
import org.apache.http.client.methods.HttpGet;
-
import org.apache.http.conn.scheme.Scheme;
-
import org.apache.http.conn.ssl.SSLSocketFactory;
-
import org.apache.http.impl.client.DefaultHttpClient;
-
-
/**
-
*
-
* @author kevin
-
*
-
*/
-
public class ClientOneWaySSL {
-
-
public final static void main(String[] args) throws Exception {
-
DefaultHttpClient httpclient = new DefaultHttpClient();
-
-
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
-
FileInputStream instream = new FileInputStream(new File("com/ssl/http/clientTruststore.jks"));
-
try {
-
trustStore.load(instream, "123456".toCharArray());
-
} finally {
-
instream.close();
-
}
-
-
SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
-
Scheme sch = new Scheme("https", socketFactory, 8443);
-
httpclient.getConnectionManager().getSchemeRegistry().register(sch);
-
-
HttpGet httpget = new HttpGet("https://w03gca01a/");
-
-
System.out.println("executing request" + httpget.getRequestLine());
-
-
HttpResponse response = httpclient.execute(httpget);
-
HttpEntity entity = response.getEntity();
-
-
System.out.println("----------------------------------------");
-
System.out.println(response.getStatusLine());
-
if (entity != null) {
-
System.out.println("Response content length: " + entity.getContentLength());
-
}
-
if (entity != null) {
-
entity.consumeContent();
-
}
-
-
// When HttpClient instance is no longer needed,
-
// shut down the connection manager to ensure
-
// immediate deallocation of all system resources
-
httpclient.getConnectionManager().shutdown();
-
}
-
-
}
6. 运行成功打印如下:
Console代码
-
executing requestGET https://w03gca01a/ HTTP/1.1
-
----------------------------------------
-
HTTP/1.1 200 OK
-
Response content length: 7347
备注:
A. 如出现如下error,请配置C:\WINDOWS\system32\drivers\etc\hosts, 将“127.0.0.1 w03gca01a” 加在hosts文件中
Exception代码
-
executing requestGET https://w03gca01a/ HTTP/1.1
-
Exception in thread "main" javax.net.ssl.SSLException: hostname in certificate didn't match: <w03gca01a> != <localhost>
-
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:220)
-
at org.apache.http.conn.ssl.BrowserCompatHostnameVerifier.verify(BrowserCompatHostnameVerifier.java:54)
-
B. 本文用到 httpcore-4.0.1.jar httpclient-4.0.1.jar httpmime-4.0.1.jar,下载地址:
http://hc.apache.org/downloads.cgi