最近产品中需要在RCP中通过SSL方式来访问Tomcat下的应用,查阅了一些资料经过调试,最终连接成功,整理过程如下
一.使用java的keytool来生成keystore和证书
1、生成服务器证书库
keytool -validity 365 -genkey -v -alias server -keyalg RSA -keystore D:\ssl\server.keystore -dname "CN=127.0.0.1,OU=disoft,O=disoft,L=ChaoYang,ST=Beijing,c=cn" -storepass 123456 -keypass 123456
2、生成客户端证书库
keytool -validity 365 -genkeypair -v -alias client -keyalg RSA -storetype PKCS12 -keystore D:\ssl\client.p12 -dname "CN=client,OU=disoft,O=disoft,L=ChaoYang,ST=Beijing,c=cn" -storepass 123456 -keypass 123456
3、从客户端证书库中导出客户端证书
keytool -export -v -alias client -keystore D:\ssl\client.p12 -storetype PKCS12 -storepass 123456 -rfc -file D:\ssl\client.cer
4、从服务器证书库中导出服务器证书
keytool -export -v -alias server -keystore D:\ssl\server.keystore -storepass 123456 -rfc -file D:\ssl\server.cer
5、生成客户端信任证书库(由服务端证书生成的证书库)
keytool -import -v -alias server -file D:\ssl\server.cer -keystore D:\ssl\client.truststore -storepass 123456
6、将客户端证书导入到服务器证书库(使得服务器信任客户端证书)
keytool -import -v -alias client -file D:\ssl\client.cer -keystore D:\ssl\server.keystore -storepass 123456
之后ssl文件夹下会有5个文件,分别是server.keystore,client.p12,client.cer,server.cer,client.truststore
注意:其中的server.keystore既是服务器的证书库,又作为服务器端对客户端的信任证书库.
步骤1中的CN最好使用IP地址,通过这个IP地址对支持SSL的server进行访问.
之后双击client.cer对客户端证书进行导入以支持浏览器的访问
用keytool生成的证书是私人的证书,并不是权威CA机构颁发的证书,但是并不影响开发。
二.配置Tomcat的SSL
Tomcat的server.xml文件需要进行相应的配置,默认这段是注释掉的,启用即可
上面的clientAuth="true"这样的设置是说明需要支持SSL双向认证.keystoreFile和keystorePass配置好自己server的keystore的路径和密码.
启动tomcat,通过https://127.0.0.1:8443 来访问
三.Eclipse RCP中通过SSL连接server
直接上代码
private static SSLContext getSSLContext() {
if (sslcontext == null) {
try {
String keystorePath = System.getProperty(TAC_SSL_SYSTEM_KEY);
String keyStorePass = System.getProperty(TAC_SSL_SYSTEM_PASS);
if (keystorePath == null) {
// if user does not set the keystore path in the .ini,we need to look for the keystore file under
// the root dir of product
String userDir = System.getProperty("user.dir");
File keystorePathFile = new File(userDir + "/" + TAC_SSL_KEYSTORE);
keystorePath = keystorePathFile.getAbsolutePath();
}
if (keyStorePass == null) {
// if user does not set the password in the .ini,we only can make it empty by
// default,but not sure the ssl can connect
keyStorePass = "";
}
File keystoreFile = new File(keystorePath);
if (!keystoreFile.canRead()) {
throw new RuntimeException("Can't find or read the SSL Keystore file at: '" + keystoreFile.getAbsolutePath()
+ "'");
}
sslcontext = SSLContext.getInstance("SSL");
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
KeyStore ks = KeyStore.getInstance("JKS");
KeyStore tks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(keystorePath), keyStorePass.toCharArray());
tks.load(new FileInputStream(keystorePath), keyStorePass.toCharArray());
kmf.init(ks, keyStorePass.toCharArray());
tmf.init(tks);
sslcontext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return sslcontext;
}上述代码是用来初始化SSL上下文,可以将生成的keystore(这里仍然是server.keystore)的路径和密码配置在RCP产品中的*.ini文件(相当于Eclipse中VM Argument的参数配置)里面,使用的时候用系统属性进行读取.
public static String getContent(String adminUrl, String urlString) throws PersistenceException {
StringBuffer buffer = new StringBuffer();
try {
URL url = new URL(adminUrl + urlString);
BufferedReader in = null;
if (adminUrl.startsWith("https://")) {
final SSLSocketFactory socketFactory = getSSLContext().getSocketFactory();
HttpsURLConnection httpsCon = (HttpsURLConnection) url.openConnection();
httpsCon.setSSLSocketFactory(socketFactory);
httpsCon.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
httpsCon.connect();
in = new BufferedReader(new InputStreamReader(httpsCon.getInputStream()));
} else {
in = new BufferedReader(new InputStreamReader(url.openStream()));
}
String inputLine;
while ((inputLine = in.readLine()) != null) {
buffer.append(inputLine);
}
in.close();
} catch (Exception e) {
throw new PersistenceException("Unable to access to url : " + adminUrl);
}
return buffer.toString();
}上述代码用java的HttpsURLConnection来建立SSL连接.
整个配置过程结束,成功连接.
|