目的:实现web项目的ssl双向认证客户端证书代码生成。
使用openssl生成ca证书和服务端证书,当然也可以通过代码实现
1)创建CA私钥,创建目录ca
openssl genrsa -out ca/ca-key.pem 1024
2)创建证书请求
openssl req -new -out ca/ca-req.csr -keyca/ca-key.pem -config openssl.cnf
在YOUR name 处一定要填写项目布置服务器所属域名或ip地址。
3)自签署证书
openssl x509 -req -in ca/ca-req.csr -outca/ca-cert.pem -signkey ca/ca-key.pem -days 3650
4)导出ca证书
openssl pkcs12 -export -clcerts -inca/ca-cert.pem -inkey ca/ca-key.pem -out ca/ca.p12
只导出 ca证书,不导出ca的秘钥
openssl pkcs12 -export -nokeys -cacerts -inca/ca-cert.pem -inkey ca/ca-key.pem -
out ca/ca1.p12
8.2 注册服务端证书
1)创建服务端密钥库,别名为server,validity有效期为365天,密钥算法为RSA, storepass密钥库密码,keypass别名条码密码。
keytool -genkey -alias server -validity 3650-keyalg RSA -keysize 1024 -keypass 123456 -storepass 123456 -keystoreserver/server.jks
在名字和姓氏处填写项目布置服务器所属域名或ip地址。
2)生成服务端证书
keytool -certreq -alias server -sigalgMD5withRSA -file server/server.csr -keypass 123456 -keystore server/server.jks-storepass 123456
3)使用CA的密钥生成服务端密钥,使用CA签证
openssl x509 -req -in server/server.csr-out server/server.pem -CA ca/ca-cert.pem -CAkey ca/ca-key.pem -days 3650-set_serial 1
4)使密钥库信任证书
keytool -import -v -trustcacerts -keypass123456 -storepass 123456 -alias root -file ca/ca-cert.pem -keystoreserver/server.jks
5)将证书回复安装在密钥库中
keytool -import -v -trustcacerts -storepass123456 -alias server -file server/server.pem -keystore server/server.jks
6)生成服务端servertrust.jks信任库
keytool -import -alias server-ca-trustcacerts -file ca/ca-cert.pem -keystore server/servertrust.jks
8.3 注册客户端证书
1)创建客户端密钥,指定用户名,下列命令中的user将替换为颁发证书的用户名
openssl genrsa -out client/user-key.pem1024
2)
openssl req -new -out client/user-req.csr-key client/user-key.pem
3)生成对应用户名的客户端证书,并使用CA签证
openssl x509 -req -in client/user-req.csr-out client/user-cert.pem -signkey client/user-key.pem -CA ca/ca-cert.pem-CAkey ca/ca-key.pem -CAcreateserial -days 3650
4)将签证之后的证书文件user-cert.pem导出为p12格式文件(p12格式可以被浏览器识别并安装到证书库中)
openssl pkcs12 -export -clcerts -inclient/user-cert.pem -inkey client/user-key.pem -out client/user.p12
5)将签证之后的证书文件user-cert.pem导入至信任秘钥库中(这里由于没有去ca认证中心购买个人证书,所以只有导入信任库才可进行双向ssl交互
keytool -import -alias user -trustcacerts-file client/user-cert.pem -keystore server/servertrust.jks
6)
keytool -list -v -alias user -keystoreserver/servertrust.jks -storepass 123456
配置weblogic
1)登录WebLogic服务器,根据图操作。
2)启用SSL
3)指定密钥库
4)配置SSL。启用双向认证。
在web.xml中配置
<!-- 登录安装数字证书 -->
<security-constraint>
<web-resource-collection>
<web-resource-name>SSL Resource</web-resource-name>
<url-pattern>/newTest.jsp</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<display-name></display-name>
java代码实现客户端证书生成,就不需要每次执行cmd命令了
package com.njcc.ssl;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class SSLTool {
private static final String serverPass = "123456";
private static Log log = LogFactory.getLog(SSLTool.class);
public static void main(String[] args) throws InterruptedException,
IOException, KeyStoreException, NoSuchAlgorithmException,
CertificateException {
createCert("user", "123");// 创建证书
boolean delVal = deleteCert("admin");// 删除证书
boolean val = updateCertPass("admin", "555555");// 更新证书密码
boolean upVal = updateServerPass("123456", "555555");// 更新信任库密码
System.out.println(val);
zssfycz("user");
}
/**
* 创建客户端证书
*
* @param alias
* clientPass file
*
* @Return boolean
*
*/
public static boolean createCert(String alias, String clientPass) {
boolean validate = validate();
if (!validate) {
System.out.println("ca和server证书文件不存在!");
return validate;
}
File directory = new File("");
String courseFile = directory.getAbsolutePath();
// 执行命令目录
File file = new File(courseFile + "\\ssl");
// 客户端信息
String subj = "\"/C=CN/ST=js/L=nj/O=smk/OU=smk/CN=" + alias + "\"";
String keyName = alias + "-key.pem";
String reqName = alias + "-req.csr";
String certName = alias + "-cert.pem";
String fileName = alias + ".p12";
// 生成客户端的私钥
String str1 = "openssl genrsa -out client/" + keyName + " 1024";
// 生成csr文件
String str2 = "openssl req -new -out client/" + reqName
+ " -key client/" + keyName + " -subj " + subj + "";
// 生成pem格式证书
String str3 = "openssl x509 -req -in client/"
+ reqName
+ " -out client/"
+ certName
+ " -signkey client/"
+ keyName
+ " -CA ca/ca-cert.pem -CAkey ca/ca-key.pem -CAcreateserial -days 3650";
// 导出p12文件
String str4 = "openssl pkcs12 -export -clcerts -in client/" + certName
+ " -inkey client/" + keyName + " -out client/" + fileName
+ " -passout pass:" + clientPass + "";
// 导入信任库
String str5 = "keytool -import -alias " + alias
+ " -trustcacerts -file client/" + certName
+ " -keystore server/servertrust.jks -storepass " + serverPass
+ "";
Process process1 = null;
Process process2 = null;
Process process3 = null;
Process process4 = null;
Process process5 = null;
int exit1;
int exit2;
int exit3;
int exit4;
int exit5;
try {
process1 = Runtime.getRuntime().exec(str1, null, file);
exit1 = process1.waitFor();
System.out.println("exit1>>>>>>" + exit1);
if (exit1 == 0) {
process2 = Runtime.getRuntime().exec(str2, null, file);
exit2 = process2.waitFor();
System.out.println("exit2>>>>>>" + exit2);
if (exit2 == 0) {
process3 = Runtime.getRuntime().exec(str3, null, file);
exit3 = process3.waitFor();
System.out.println("exit3>>>>>>" + exit3);
if (exit3 == 0) {
process4 = Runtime.getRuntime().exec(str4, null, file);
exit4 = process4.waitFor();
System.out.println("exit4>>>>>>" + exit4);
if (exit4 == 0) {
process5 = Runtime.getRuntime().exec(str5, null,
file);
exit5 = process5.waitFor();
System.out.println("exit5>>>>>>" + exit5);
if (exit5 == 0) {
System.out.println("证书生成成功。");
log.info(alias + "证书生成成功。");
// 写文件
writeSerNum(alias, clientPass, courseFile);
return true;
} else {
log.error("执行命令:" + str5 + " 出错。");
}
} else {
log.error("执行命令:" + str4 + " 出错。");
}
} else {
log.error("执行命令:" + str3 + " 出错。");
}
} else {
log.error("执行命令:" + str2 + " 出错。");
}
} else {
log.error("执行命令:" + str1 + " 出错。");
}
} catch (IOException e) {
log.error("createCert方法:" + e);
e.printStackTrace();
} catch (InterruptedException e) {
log.error("createCert方法:" + e);
e.printStackTrace();
} finally {
// 杀死子进程
if (process1 != null) {
process1.destroy();
process1 = null;
if (process2 != null) {
process2.destroy();
process2 = null;
if (process3 != null) {
process3.destroy();
process3 = null;
if (process4 != null) {
process4.destroy();
process4 = null;
if (process5 != null) {
process5.destroy();
process5 = null;
}
}
}
}
}
}
return false;
}
/**
* 删除证书条目
*
* @param alias
* 证书别名
* @Return boolean
*
*/
public static boolean deleteCert(String alias) {
boolean validate = validate();
if (!validate) {
System.out.println("ca和server证书文件不存在!");
return validate;
}
File directory = new File("");
String courseFile = directory.getAbsolutePath();
// 执行命令目录
File file = new File(courseFile + "\\ssl");
String str = "keytool -delete -alias " + alias
+ " -keystore server/servertrust.jks -storepass " + serverPass
+ "";
int val = 1;
Process process = null;
try {
process = Runtime.getRuntime().exec(str, null, file);
val = process.waitFor();
} catch (IOException e) {
log.error("deleteCert方法:" + e);
e.printStackTrace();
} catch (InterruptedException e) {
log.error("deleteCert方法:" + e);
e.printStackTrace();
} finally {
process.destroy();
process = null;
}
if (val == 1) {
log.error("删除证书条目时,执行命令:" + str + " 出错");
}
// 0代表删除成功,1代表删除失败
return val == 0 ? true : false;
}
/**
* 更新证书条目密码
*
* @param alias
* newPass 证书别名 新密码
* @Return boolean
*
*/
public static boolean updateCertPass(String alias, String newPass) {
// alias = "user";
// newPass = "111111";
// serverPass = "123456";
// // 更新是否成功
// int val = 1;
// int del = deleteCert(alias, serverPass, file);
// if (del == 0) {
// createCert(alias,newPass, serverPass, file);
// } else {
// System.out.println("删除失败");
// val = del;
// }
// return val;
boolean validate = validate();
if (!validate) {
System.out.println("ca和server证书文件不存在!");
return validate;
}
File directory = new File("");
String courseFile = directory.getAbsolutePath();
// 执行命令目录
File file = new File(courseFile + "\\ssl");
String keyName = alias + "-key.pem";
String certName = alias + "-cert.pem";
String fileName = alias + ".p12";
if (!new File(courseFile + "\\ssl\\client\\" + keyName + "").exists()
|| !new File(courseFile + "\\ssl\\client\\" + certName + "")
.exists()) {
log.error("更新证书密码时," + keyName + "或" + certName + "文件不存在");
System.out.println(keyName + "或" + certName + "文件不存在");
return false;
}
String str = "openssl pkcs12 -export -clcerts -in client/" + certName
+ " -inkey client/" + keyName + " -out client/" + fileName
+ " -passout pass:" + newPass + "";
int val = 1;
Process process = null;
try {
process = Runtime.getRuntime().exec(str, null, file);
val = process.waitFor();
} catch (IOException e) {
log.error("updateCertPass方法:" + e);
e.printStackTrace();
} catch (InterruptedException e) {
log.error("updateCertPass方法:" + e);
e.printStackTrace();
} finally {
process.destroy();
process = null;
}
if (val == 1) {
log.error("更新证书密码时,执行命令:" + str + " 出错");
}
// 0代表删除成功,1代表删除失败
return val == 0 ? true : false;
}
/**
* 更新信任库密码
*
* @param oldPass
* newPass file 原密码 新密码
* @Return val 0代表更新成功,1代表更新失败
*
*/
public static boolean updateServerPass(String oldPass, String newPass) {
boolean validate = validate();
if (!validate) {
System.out.println("ca和server证书文件不存在!");
return validate;
}
File directory = new File("");
String courseFile = directory.getAbsolutePath();
// 执行命令目录
File file = new File(courseFile + "\\ssl");
String str = "keytool -storepasswd -keystore server/servertrust.jks -storepass "
+ oldPass + " -new " + newPass + "";
int val = 1;
Process process = null;
try {
process = Runtime.getRuntime().exec(str, null, file);
val = process.waitFor();
} catch (IOException e) {
log.error("updateServerPass方法:" + e);
e.printStackTrace();
} catch (InterruptedException e) {
log.error("updateServerPass方法:" + e);
e.printStackTrace();
} finally {
process.destroy();
process = null;
}
// 0代表删除成功,1代表删除失败
return val == 0 ? true : false;
}
/**
* 记录证书系列号
*
* @param alias
* file 证书别名 文件目录
*
*
*/
private static void writeSerNum(String alias, String pass, String path) {
// 信任库文件servertrust.jks
String storePath = path + "\\ssl\\server\\servertrust.jks";
// 记录证书系列号的文件
File txtFile = new File(path + "\\ssl\\客户端证书系列信息.txt");
FileInputStream in = null;
FileWriter writer = null;
KeyStore ks;
try {
in = new FileInputStream(storePath);
ks = KeyStore.getInstance("JKS");
ks.load(in, serverPass.toCharArray());
X509Certificate c = (X509Certificate) ks.getCertificate(alias);
// alias为条目的别名
String serialNumber = c.getSerialNumber().toString(16);
Date today = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str = "生成时间 : " + sf.format(today) + "\r\n" + "证书名称 : "
+ alias + "\r\n" + "安装密码 : " + pass + "\r\n" + "证书系列号: "
+ serialNumber + "\r\n\r\n\r\n";
if (!txtFile.exists()) {
boolean createNewFile = txtFile.createNewFile();
if (!createNewFile) {
log.error("生成客户端证书系列信息文件失败,请手动记录证书信息:" + str);
throw new Exception();
}
}
writer = new FileWriter(txtFile, true);
// if(txtFile.length() == 0){
// writer.write(" 生成时间 " + " 用户名称 " + " 用户密码 " +
// " 证书系列号 \n ");
// writer.flush();
// }
writer.write(str);
writer.flush();
} catch (NoSuchAlgorithmException e) {
log.error("writeSerNum方法:" + e);
e.printStackTrace();
} catch (KeyStoreException e) {
log.error("writeSerNum方法:" + e);
e.printStackTrace();
} catch (CertificateException e) {
log.error("writeSerNum方法:" + e);
e.printStackTrace();
} catch (IOException e) {
log.error("writeSerNum方法:" + e);
e.printStackTrace();
} catch (Exception e) {
log.error("生成客户端证书系列信息文件失败,请手动记录证书信息:" + e);
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 验证ssl 所需ca和server文件是否存在
*
* @return
*/
public static boolean validate() {
boolean val = false;
File directory = new File("");
String courseFile = directory.getAbsolutePath();
File file = new File(courseFile + "\\ssl\\client");
if (!file.exists()) {
boolean mkdirs = file.mkdirs();
if (!mkdirs) {
log.error("创建" + file.getAbsolutePath() + "文件夹失败");
return false;
}
}
if (new File(courseFile + "\\ssl\\ca\\ca-cert.pem").exists()
&& new File(courseFile + "\\ssl\\ca\\ca-key.pem").exists()
&& new File(courseFile + "\\ssl\\server\\servertrust.jks")
.exists()) {
val = true;
}
if (!val) {
log.error("ca和server证书相关文件不存在!");
}
return val;
}
//判断证书是否已经存在
public static boolean zssfycz(String alias) {
File directory = new File("");
String courseFile = directory.getAbsolutePath();
String storePath = courseFile + "\\ssl\\server\\servertrust.jks";
boolean val = false;
try {
FileInputStream in = new FileInputStream(storePath);
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(in, serverPass.toCharArray());
val = ks.containsAlias(alias);
} catch (Exception e) {
log.error("zssfycz方法:" + e);
e.printStackTrace();
}// 检验条目是否在密钥库中,存在返回true
// Process process = null;
// try {
// File directory = new File("");
// String courseFile = directory.getAbsolutePath();
// //执行命令目录
// File file = new File(courseFile+"\\ssl");
// //判断信任库中是否存在该证书
// String str =
// "keytool -list -v -alias "+alias+" -keystore server/servertrust.jks -storepass 123456";
// //1代表信任库中没有导入客户端证书
// process = Runtime.getRuntime().exec(str, null, file);
// int exit = process.waitFor();
// if(exit == 1){
// return false;
// }
// } catch (IOException e) {
// log.error("zssfycz方法:"+e);
// e.printStackTrace();
// } catch (InterruptedException e) {
// log.error("zssfycz方法:"+e);
// e.printStackTrace();
// }
System.out.println(val);
return val;
}
//实现cmd 输入信息交互
private static int handleImport(Process process,String...params) throws IOException {
InputStream inputStream = process.getInputStream();
OutputStreamWriter outputStream = new OutputStreamWriter(process
.getOutputStream());
if(params!=null&¶ms.length>0){
for(int i=0;i<params.length;i++){
outputStream.write(params[i]);
outputStream.flush();
}
}
BufferedReader reader = new BufferedReader(new InputStreamReader(
inputStream));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
inputStream = process.getErrorStream();
int val = process.exitValue();
inputStream.close();
inputStream = null;
return val;
}
}