我正在使用自签名证书进行 SSL双向身份验证。 我为客户端(client-keystore.jks)和服务器(server-keystore.jks)创建了两个密钥库,从密钥库导出证书并导入客户端证书到服务器密钥库和服务器证书进入客户端密钥库。并在 server.xml 中更新了所需的连接器条目,并将这两个证书添加到了Java信任库 cacerts 。
Java客户端代码:
KeyStore trustStore = KeyStore.getInstance("JKS", "SUN");
trustStore.load(SSLImplemetation.class.getResourceAsStream("C:/Program Files/Java/jdk1.7.0_79/jre/lib/security/cacerts"), "changeit".toCharArray());
String alg = KeyManagerFactory.getDefaultAlgorithm();
TrustManagerFactory fac = TrustManagerFactory.getInstance(alg);
fac.init(trustStore);
KeyStore keystore = KeyStore.getInstance("JKS", "SUN");
keystore.load(SSLImplemetation.class.getResourceAsStream("<dir path>/client-keystore.jks"), "test".toCharArra());
String keyAlg = KeyManagerFactory.getDefaultAlgorithm();
KeyManagerFactory keyFac = KeyManagerFactory.getInstance(keyAlg);
keyFac.init(keystore, "test".toCharArray());
SSLContext ctx = SSLContext.getInstance("TLS", "SunJSSE");
ctx.init(keyFac.getKeyManagers(),fac.getTrustManagers(), new SecureRandom());
SslContextedSecureProtocolSocketFactory secureProtocolSocketFactory = new SslContextedSecureProtocolSocketFactory(ctx);
Protocol.registerProtocol("https", new Protocol("https", (ProtocolSocketFactory) secureProtocolSocketFactory, 8443));
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpPost request = new HttpPost("<rest service url>");
JSONObject obj = new JSONObject();
StringEntity params =new StringEntity(obj.toString());
request.addHeader("content-type", "application/json");
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
System.out.println(response.getStatusLine());
server.xml中:
<Connector
protocol="org.apache.coyote.http11.Http11Protocol"
port="8443" maxThreads="200" scheme="https" secure="true" SSLEnabled="true"
clientAuth="true" sslProtocol="TLS"
keystoreFile="<dir path>/server-keystore.jks" keystorePass="test"
truststoreFile="C:/Program Files/Java/jdk1.7.0_79/jre/lib/security/cacerts"
truststorePass="changeit" />
我是SSl的新手,所以有点困惑。 任何帮助将不胜感激。
答案 0 :(得分:0)
下面的代码对我来说很好,在创建了两个客户端和服务器密钥库并将证书放入java信任库后,我使用了以下代码进行SSL相互认证。
static final private String KEY_STORE = "D:/sslcertificates/client-keystore.jks";
static final private String KEY_STORE_TYPE = "JKS";
static final private String KEY_STORE_PASS = "test";
public static void main(String[] args) throws JSONException{
try {
URL url = new URL("<rest service url>");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setHostnameVerifier(new HostnameVerifier(){
public boolean verify(String hostname,
javax.net.ssl.SSLSession sslSession) {
if (hostname.equals("<hostname>")) {
return true;
}
return false;
}
});
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
try
{
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509","SunJSSE");
KeyStore ks = KeyStore.getInstance(KEY_STORE_TYPE);
File cert = new File(KEY_STORE);
InputStream stream = new FileInputStream(cert);
ks.load(stream, KEY_STORE_PASS.toCharArray());
stream.close();
kmf.init(ks,KEY_STORE_PASS.toCharArray());
SSLContext context = SSLContext.getInstance("TLS");
context.init(kmf.getKeyManagers(),null, new SecureRandom());
SSLSocketFactory factory = context.getSocketFactory();
conn.setSSLSocketFactory(factory);
}
catch(Exception e)
{
System.out.println(e);
}
JSONObject obj = new JSONObject();
obj.put("id","abc");
obj.put("name","surya");
obj.put( "domain","IT");
String input=obj.toString();
//send request to server....
OutputStream os = conn.getOutputStream();
os.write(input.getBytes());
os.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
}
System.out.println("Response code: "+conn.getResponseCode());
System.out.println("Response message: "+conn.getResponseMessage());
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
的Server.xml
<Connector
protocol="org.apache.coyote.http11.Http11Protocol"
port="8443" maxThreads="200" scheme="https" secure="true" SSLEnabled="true"
clientAuth="true" sslProtocol="TLS"
keystoreFile="<dir path>/server-keystore.jks" keystorePass="test"/>
注意:在HttpsURLConnection对象中设置HostnameVerifier,客户端和服务器密钥库的CN应该是主机名。
如果有更好的解决方案,请提出建议。