参考文章:http://blog.csdn.net/cuker919/article/details/7599969
一、单向认证
链接一般的SSL时采用的是单向验证,客户机只验证服务器的证书,服务器不验证客户机的证书。Tomcat将HTTPS端口设置为8443,参考Tomcat配置Https协议。
package com.learn.http;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
public class HttpsSend {
public static void main(String[] args) {
HttpsSend send = new HttpsSend();
send.https();
}
public void https() {
CloseableHttpClient httpclient = null;
try {
//SSLContext 用来创建定制SSL连接
SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
new DefaultHostnameVerifier());
httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
HttpGet httpget = new HttpGet("https://192.168.0.108:8443/");
System.out.println("executing request" + httpget.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httpget);
try {
HttpEntity entity = response.getEntity();
System.out.println("---------------------------------");
System.out.println(response.getStatusLine());
if (entity != null) {
System.out.println("Response content length: " + entity.getContentLength());
System.out.println(EntityUtils.toString(entity));
EntityUtils.consume(entity);
}
} finally {
response.close();
}
} catch (KeyManagementException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
if(httpclient != null)
{
try {
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
二、双向认证
SSL进行双向身份验证意思就是在客户机连接服务器时,链接双方都要对彼此的数字证书进行验证,保证这是经过授权的才能够连接。
1、生成key和证书
1)生成服务端私钥,并且导入到服务端KeyStore文件中
keytool -genkey -alias serverkey -keystore serverKey.keystore
2)根据私钥,导出服务端证书
keytool -export -alias serverkey -keystore serverKey.keystore -file server.crt
server.crt就是服务端的证书
3)将服务端证书,导入到客户端的Trust KeyStore中
keytool -import -alias serverkey -file server.crt -keystore serverCrt.keystore
serverCrt.keystore是给客户端用户,其中保存着受信任的证书
采用同样的方法,生成客户端的私钥,客户端的证书,并且导入到服务端的Trust KeyStore中
1)keytool -genkey -alias clientkey -keystore clientKey.keystore
2)keytool -export -alias clientkey -keystore clientKey.keystore -file client.crt
3)keytool -import -alias clientkey -file client.crt -keystore clientCrt.keystore
2、Tomcat Server.xml配置
<Connector>配置里的属性参数:clientAuth设为true即为双向认证。(IP:192.168.0.108)
Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="true" sslProtocol="TLS"
keystoreFile="conf/serverKey.keystore" keystorePass="skysky"
truststoreFile="conf/clientCrt.keystore" truststorePass="skysky"/>
3、请求示例(请求上述配置的Tomcat):
package com.learn.http;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class HttpsSend2 {
public static void main(String[] args) {
new HttpsSend2().ssl("https://192.168.0.108:8443/");
}
public void ssl(String url)
{
CloseableHttpClient httpclient = null;
try
{
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream instream = new FileInputStream(new File("d:\\clientKey.keystore"));
KeyStore trustStore2 = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream instream2 = new FileInputStream(new File("d:\\serverCrt.keystore"));
try
{
trustStore.load(instream, "skysky".toCharArray());
trustStore2.load(instream2, "skysky".toCharArray());
}
catch (CertificateException e)
{
e.printStackTrace();
}
finally
{
try
{
instream.close();
instream2.close();
}
catch(Exception ignore)
{
}
}
//客户端私钥 SunX509 :Sun公司提供的X509算法
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(trustStore, "skysky".toCharArray());
//服务端证书
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(trustStore2);
//创建定制SSL连接
SSLContext sslcontext = SSLContext.getInstance("TLSv1");
sslcontext.init(kmf.getKeyManagers(),tmf.getTrustManagers(),null);
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext);
httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
HttpGet httpget = new HttpGet(url);
System.out.println("executing request" + httpget.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httpget);
try
{
HttpEntity entity = response.getEntity();
System.out.println("---------------------------");
System.out.println(response.getStatusLine());
if(entity != null)
{
System.out.println("Response content Length:" + entity.getContentLength());
System.out.println(EntityUtils.toString(entity));
EntityUtils.consume(entity);
}
}
finally
{
response.close();
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if(httpclient != null)
{
try
{
httpclient.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
}
}