java代码实现证书生成客户端证书 实现ssl双向认证

目的:实现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;
	}
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值