keyring内置证书导入功能

This commit is contained in:
段冬梅
2019-06-14 10:20:13 +08:00
parent 1031b0a118
commit b280c23021
6 changed files with 446 additions and 5 deletions

View File

@@ -13,6 +13,7 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
@@ -34,6 +35,7 @@ import org.springframework.ui.Model;
import org.springframework.util.FileCopyUtils; import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes; import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@@ -370,6 +372,19 @@ public class PxyObjKeyringController extends BaseController {
// 查询时left join policyGroup // 查询时left join policyGroup
Page<PxyObjKeyring> page = pxyObjKeyringService.findPage(new Page<PxyObjKeyring>(request, response, "r"), Page<PxyObjKeyring> page = pxyObjKeyringService.findPage(new Page<PxyObjKeyring>(request, response, "r"),
entity); entity);
//查询是否存在内置配置
PxyObjKeyring searchEntity=new PxyObjKeyring();
searchEntity.setCompileId(0);
Page<PxyObjKeyring> searchPage=new Page<PxyObjKeyring>();
Page<PxyObjKeyring> builtInPage = pxyObjKeyringService.findPage(searchPage,
searchEntity);
if(builtInPage != null && !StringUtil.isEmpty(builtInPage.getList())) {
model.addAttribute("hasBuiltIn", true);
}else {
model.addAttribute("hasBuiltIn", false);
}
model.addAttribute("page", page); model.addAttribute("page", page);
initPageCondition(model, entity); initPageCondition(model, entity);
return "/cfg/intercept/strateagy/list"; return "/cfg/intercept/strateagy/list";
@@ -608,8 +623,9 @@ public class PxyObjKeyringController extends BaseController {
searchBuiltIn.setBuiltIn(1); searchBuiltIn.setBuiltIn(1);
searchBuiltIn.setIsValid(1); searchBuiltIn.setIsValid(1);
searchBuiltIn.setIsAudit(1); searchBuiltIn.setIsAudit(1);
Page<PxyObjTrustedCaCert> searchPage =new Page<PxyObjTrustedCaCert>();
Page<PxyObjTrustedCaCert> builtInReslt = pxyObjKeyringService Page<PxyObjTrustedCaCert> builtInReslt = pxyObjKeyringService
.findTrustedCertPage(new Page<PxyObjTrustedCaCert>(request, response, "r"), searchBuiltIn); .findTrustedCertPage(searchPage, searchBuiltIn);
if(builtInReslt != null && !StringUtil.isEmpty(builtInReslt.getList())) { if(builtInReslt != null && !StringUtil.isEmpty(builtInReslt.getList())) {
model.addAttribute("hasBuiltIn", true); model.addAttribute("hasBuiltIn", true);
}else { }else {
@@ -858,6 +874,17 @@ public class PxyObjKeyringController extends BaseController {
return "redirect:" + adminPath + "/proxy/intercept/strateagy/trustedCertList?functionId=" + cfg.getFunctionId(); return "redirect:" + adminPath + "/proxy/intercept/strateagy/trustedCertList?functionId=" + cfg.getFunctionId();
} }
/**
* 内置可信证书导入
* @param model
* @param request
* @param response
* @param cfg
* @param crlFileI
* @param redirectAttributes
* @return
*/
@RequestMapping(value = { "/addBuiltInCert" }) @RequestMapping(value = { "/addBuiltInCert" })
public String trustedCertBuiltIn(Model model, HttpServletRequest request, HttpServletResponse response, public String trustedCertBuiltIn(Model model, HttpServletRequest request, HttpServletResponse response,
@ModelAttribute("cfg") PxyObjTrustedCaCert cfg, MultipartFile crlFileI, @ModelAttribute("cfg") PxyObjTrustedCaCert cfg, MultipartFile crlFileI,
@@ -1040,6 +1067,220 @@ public class PxyObjKeyringController extends BaseController {
return "redirect:" + adminPath + "/proxy/intercept/strateagy/trustedCertList?functionId=" + cfg.getFunctionId(); return "redirect:" + adminPath + "/proxy/intercept/strateagy/trustedCertList?functionId=" + cfg.getFunctionId();
} }
/**
* 内置Keyring 导入功能
* @param model
* @param request
* @param response
* @param cfg
* @param certFileI
* @param redirectAttributes
* @return
*/
@RequestMapping(value = { "/addKeyRingBuiltInCert" })
public String addKeyRingBuiltInCert(Model model, HttpServletRequest request, HttpServletResponse response,
@ModelAttribute("cfg") PxyObjKeyring cfg, @RequestParam("certFileI")MultipartFile[] certFileI,
RedirectAttributes redirectAttributes) {
logger.info("keyring内置证书开始校验");
boolean validFlag = true;
//每个证书文件的内容
Map<String, Map> fileCertMap=new HashMap<>();
try {
if(certFileI != null && certFileI.length > 0) {
for (MultipartFile multipartFile : certFileI) {
//校验证书格式
boolean certFileflag = validCertFileContent(multipartFile,null, "-incert");
logger.info("证书列表校验结果"+certFileflag);
if (!certFileflag) {
addMessage(redirectAttributes, "error", "save_failed");
logger.error(multipartFile.getOriginalFilename() + " file non crl file format ");
throw new MultiPartNewException(this.getMsgProp().getProperty("cert_file_error"));
}else {
if(!certInfoMap.isEmpty()) {
String issuer = StringUtil.isEmpty(certInfoMap.get("ca issuer")) ? ""
: certInfoMap.get("ca issuer").toString();// 颁发者
String fingerprint = StringUtil.isEmpty(certInfoMap.get("ca fingerprint")) ? ""
: certInfoMap.get("ca fingerprint").toString();// 指纹
if(!StringUtil.isEmpty(issuer) && !StringUtil.isEmpty(fingerprint)) {
if(Constants.KEYRING_BUILT_IN_ISSER.contains("||"+issuer+"||")
&& Constants.KEYRING_BUILT_IN_FINGERPRINT.contains("||"+fingerprint+"||")) {
fileCertMap.put(multipartFile.getOriginalFilename(), certInfoMap);
}else {
validFlag=false;
break;
}
}else {
validFlag=false;
break;
}
}else {
validFlag=false;
break;
}
}
}
}else {
addMessage(redirectAttributes, "error", "save_failed");
logger.error(" keyring is null ");
throw new Exception();
}
} catch (Exception e) {
validFlag = false;
logger.error("证书文件校验失败", e);
if (e instanceof MaatConvertException) {
addMessage(redirectAttributes, "error", "request_service_failed");
LogUtils.saveLog(request, null, e, null);
} else if (e instanceof MultiPartNewException) {
addMessage(redirectAttributes, "error", e.getMessage());
LogUtils.saveLog(request, null, e, null);
} else {
addMessage(redirectAttributes, "error", "save_failed");
LogUtils.saveLog(request, null, e, null);
}
}
List<PxyObjKeyring> keyringList=new ArrayList<PxyObjKeyring>();
//是keyring内置证书且验证通过进行证书文件上传
try {
if(validFlag) {
File file=null;
for (MultipartFile certFile :certFileI) {
PxyObjKeyring keyring=new PxyObjKeyring();
BeanUtils.copyProperties(cfg, keyring);
/**************************证书信息获取*************************************/
String issuer = StringUtil.isEmpty(fileCertMap.get(certFile.getOriginalFilename()).get("ca issuer")) ? ""
: fileCertMap.get(certFile.getOriginalFilename()).get("ca issuer").toString();// 颁发者
String subject = StringUtil.isEmpty(fileCertMap.get(certFile.getOriginalFilename()).get("ca subjectname")) ? ""
: fileCertMap.get(certFile.getOriginalFilename()).get("ca subjectname").toString();// 颁发给
String notBeforeStr = "";
if (!StringUtil.isEmpty(fileCertMap.get(certFile.getOriginalFilename()).get("ca notbefore"))) {
Date notBeforeTime = new Date(fileCertMap.get(certFile.getOriginalFilename()).get("ca notbefore").toString());// 开始时间
notBeforeStr = sdf.format(notBeforeTime);
}
String notAfterStr = "";
if (!StringUtil.isEmpty(fileCertMap.get(certFile.getOriginalFilename()).get("ca notafter"))) {
Date notAfterTime = new Date(fileCertMap.get(certFile.getOriginalFilename()).get("ca notafter").toString());// 结束时间
notAfterStr = sdf.format(notAfterTime);
}
String cn = "";// CN
// CN精确信息获取
if (!StringUtil.isEmpty(subject)) {
for (String cnStr : subject.split(",")) {
cnStr = StringUtil.isEmpty(cnStr) ? "" : cnStr.trim();
if (cnStr.split("=").length > 1) {
cn = cnStr.split("=")[1];
cn = StringUtil.isEmpty(cn) ? "" : cn.trim();
}
}
}
String altName = StringUtil.isEmpty(fileCertMap.get(certFile.getOriginalFilename()).get("ca altname")) ? ""
: fileCertMap.get(certFile.getOriginalFilename()).get("ca altname").toString();// SAN
keyring.setIssuer(issuer);
keyring.setSubject(subject);
keyring.setCn(cn);
keyring.setAltName(altName);
keyring.setNotBeforeTime(notBeforeStr);
keyring.setNotAfterTime(notAfterStr);
keyring.setKeyringType("root");
keyring.setExpireAfter(30);
keyring.setCrl("");
keyring.setPublicKeyAlgo("");
/**************************公私钥文件上传*************************************/
if (certFile != null) {
String filename = certFile.getOriginalFilename();
String prefix = FileUtils.getPrefix(filename, false);
keyring.setKeyringName(prefix);
keyring.setCfgDesc(prefix);
String suffix = FileUtils.getSuffix(filename, false);
file = File.createTempFile("file_" + prefix, FileUtils.getSuffix(filename, true));
certFile.transferTo(file);// 复制文件
String md5 = FileUtils.getFileMD5(file);
Map<String, Object> srcMap = Maps.newHashMap();
srcMap.put("filetype", suffix);
srcMap.put("datatype", "dbSystem");// 源文件存入数据中心
srcMap.put("createTime", new Date());
srcMap.put("key", prefix);
srcMap.put("fileName", filename);
srcMap.put("checksum", md5);
ToMaatResult result = ConfigServiceUtil.postFileCfg(null, file, JsonMapper.toJsonString(srcMap));
logger.info("proxy 证书文件策略公钥 文件上传响应信息:" + JsonMapper.toJsonString(result));
String publicKeyFileAccessUrl = null;
if (!StringUtil.isEmpty(result)) {
ResponseData data = result.getData();
publicKeyFileAccessUrl = data.getAccessUrl();
keyring.setPublicKeyFile(publicKeyFileAccessUrl);
}
}
if (certFile != null) {
String filename = certFile.getOriginalFilename();
String prefix = FileUtils.getPrefix(filename, false);
String suffix = FileUtils.getSuffix(filename, false);
file = File.createTempFile("file_" + prefix, FileUtils.getSuffix(filename, true));
certFile.transferTo(file);// 复制文件
String md5 = FileUtils.getFileMD5(file);
Map<String, Object> srcMap = Maps.newHashMap();
srcMap.put("filetype", suffix);
srcMap.put("datatype", "dbSystem");// 源文件存入数据中心
srcMap.put("createTime", new Date());
srcMap.put("key", prefix);
srcMap.put("fileName", filename);
srcMap.put("checksum", md5);
ToMaatResult result = ConfigServiceUtil.postFileCfg(null, file, JsonMapper.toJsonString(srcMap));
logger.info("proxy 证书文件策略私钥 上传响应信息:" + JsonMapper.toJsonString(result));
String privateKeyFileAccessUrl = null;
if (!StringUtil.isEmpty(result)) {
ResponseData data = result.getData();
privateKeyFileAccessUrl = data.getAccessUrl();
keyring.setPrivateKeyFile(privateKeyFileAccessUrl);
;
}
}
logger.info(keyring.getPublicKeyFile());
logger.info(keyring.getPrivateKeyFile());
keyringList.add(keyring);
}
}
} catch (MultiPartNewException e) {
logger.error("证书文件上传失败:",e);
addMessage(redirectAttributes, "error", "request_service_failed");
LogUtils.saveLog(request, null, e, null);
} catch (MaatConvertException e) {
logger.error("策略配置下发失败:",e);
addMessage(redirectAttributes, "error", "request_service_failed");
LogUtils.saveLog(request, null, e, null);
} catch (Exception e) {
logger.error("策略配置保存失败:",e);
addMessage(redirectAttributes, "error", "save_failed");
LogUtils.saveLog(request, null, e, null);
}
try {
if(!StringUtil.isEmpty(keyringList)) {
pxyObjKeyringService.saveAndAuditKeyring(keyringList);
//配置仅保存
if(StringUtil.isEmpty(cfg.getIsValid()) || cfg.getIsValid()!=1) {
addMessage(redirectAttributes, "success", "save_success");
}else {
//配置直接生效
addMessage(redirectAttributes, "success", "audit_success");
}
}
} catch (MaatConvertException e) {
logger.error("策略配置下发失败:",e);
addMessage(redirectAttributes, "error", "request_service_failed");
LogUtils.saveLog(request, null, e, null);
} catch (Exception e) {
logger.error("策略配置保存失败:",e);
addMessage(redirectAttributes, "error", "save_failed");
LogUtils.saveLog(request, null, e, null);
}
return "redirect:" + adminPath + "/proxy/intercept/strateagy/list?functionId=" + cfg.getFunctionId();
}
/** /**
* 调用shell脚本 返回运行结果 * 调用shell脚本 返回运行结果
* *

View File

@@ -467,8 +467,8 @@
#{cfgId,jdbcType=VARCHAR}, #{cfgId,jdbcType=VARCHAR},
#{cfgDesc,jdbcType=VARCHAR}, #{cfgDesc,jdbcType=VARCHAR},
#{action,jdbcType=INTEGER}, #{action,jdbcType=INTEGER},
0, #{isValid,jdbcType=INTEGER},
0, #{isAudit,jdbcType=INTEGER},
#{creatorId,jdbcType=INTEGER}, #{creatorId,jdbcType=INTEGER},
#{createTime,jdbcType=TIMESTAMP}, #{createTime,jdbcType=TIMESTAMP},
#{editorId,jdbcType=INTEGER}, #{editorId,jdbcType=INTEGER},

View File

@@ -533,6 +533,48 @@ public class PxyObjKeyringService extends BaseService{
throw e; throw e;
} }
} }
@Transactional(readOnly=false,rollbackFor=RuntimeException.class)
public void saveAndAuditKeyring(List<PxyObjKeyring> cfgList){
Date date=new Date();
for (PxyObjKeyring cfg : cfgList) {
//0为不可信证书1可信证书
if(cfg.getIssuer().indexOf("UNTRUST") > -1) {
cfg.setCompileId(0);
}else {
cfg.setCompileId(1);
}
cfg.setCreateTime(date);
cfg.setCreatorId(UserUtils.getUser().getId());
cfg.setAuditTime(date);
cfg.setAuditorId(UserUtils.getUser().getId());
logger.info(cfg.getPublicKeyFile());
logger.info(cfg.getPrivateKeyFile());
pxyObjKeyringDao.insert(cfg);
}
String json="";
List<ProxyObjKeyring> keyRingList=new ArrayList<ProxyObjKeyring>();
//可信证书cert回调配置转换
for (PxyObjKeyring cfg : cfgList) {
keyRingList.add(convertCallBackProxyObjKeyring(cfg));
}
//调用服务接口下发配置数据
json=gsonToJson(keyRingList);
logger.info("keyring内置证书下发配置参数"+json);
//调用服务接口下发配置
try {
ToMaatResult result = ConfigServiceUtil.postCallbackCfg(json);
if(result!=null){
logger.info("keyring内置证书下发响应信息"+result.getMsg());
}
} catch (Exception e) {
logger.error("keyring内置证书下发失败",e);
throw e;
}
}
} }

View File

@@ -0,0 +1,140 @@
<%@ page contentType="text/html;charset=UTF-8"%>
<%@ include file="/WEB-INF/include/taglib.jsp"%>
<<script type="text/javascript">
$(function(){
$("#certFileInfo,#uploadCertFile").on('click', function() {
$("#certFileI").trigger("click");
});
$("#certFileI").on('change', function() {
$("#certFileInfo").val($("#certFileI").val());
/* certFileValidate(); */
});
});
//增加对文件后缀名验证
function certFileValidate(){
var flag=false; //状态,检测文件后缀用
var arr=["cert"];
var cFile=$("#certFileI").val();//文件的值
//取出上传文件的扩展名
var index=cFile.lastIndexOf(".");
var ext = cFile.substr(index+1).toLowerCase();
//循环比较
for(var i=0;i<arr.length;i++)
{
if(ext == arr[i])
{
flag = true; //一旦找到合适的,立即退出循环
break;
}
}
//条件判断
$("div[for='certFileInfo']").empty();
$(".alert-error").addClass("hide");
if(!flag){
// ("文件名不合法");
$("div[for='certFileInfo']").empty();
$(".alert-error").removeClass("hide");
$("div[for='certFileInfo']").append("<label id='level-error' class='error'><spring:message code='file_in_wrong_format'/></label>");
return false;
}
return true;
}
var submitCertFrom=function(){
var certFile = $("#certFileI").val();
/* if(certFile!=''){
if(!certFileValidate()){
return false;
}
} */
certFile=$("#certFileInfo").val();
if((certFile==null || certFile=="")){
$("div[for='certFileInfo']").empty();
$(".alert-error").removeClass("hide");
$("div[for='certFileInfo']").append("<label id='level-error' class='error' for='certFileI'><spring:message code='required'/></label>");
return false;
}else{
$("div[for='certFileInfo']").empty();
$(".alert-error").addClass("hide");
loading('onloading...');
$("#certForm").submit();
}
}
</script>
<div class="modal fade" id="add_cert_modal" tabindex="-1" role="dialog" aria-labelledby="mo" aria-hidden="true">
<form id="certForm" action="${ctx}/proxy/intercept/strateagy/addKeyRingBuiltInCert?importPath=${importPath}" method="post" enctype="multipart/form-data" class="form-horizontal"
onsubmit="loading('<spring:message code='loading'/>');">
<input type="hidden" id="certTip" value="<spring:message code='cert_tip'/>">
<div class="modal-dialog" role="document" style="width:700px;">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">
<spring:message code="import_built_cert_file" />
</h5>
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="alert alert-error hide">
<!-- <button class="close" data-dismiss="alert"></button> -->
<span><div for="certFileInfo"></div></span>
</div>
<!-- 同主表cert配置信息 -->
<input type="hidden" name="cfgDesc" value="">
<input type="hidden" name="action" value="1">
<input type="hidden" name="isValid" value="1">
<input type="hidden" name="isAudit" value="1">
<input type="hidden" name="functionId" value="${cfg.functionId }">
<input type="hidden" name="serviceId" value="520">
<input type="hidden" name="cfgRegionCode" value="">
<input type="hidden" name="requestId" value="0">
<input type="hidden" name="isAreaEffective" value="0">
<input type="hidden" name="areaEffectiveIds" value="0">
<input type="hidden" name="classify" value="0"/>
<input type="hidden" name="attribute" value="0"/>
<input type="hidden" name="lable" value="0"/>
<input type="hidden" name="cancelRequestId" value=""/>
</br>
<div class="col-md-12">
<div class="form-group">
<label class="control-label col-md-3"><font
color="red">*</font><spring:message code="certificate" /> <spring:message code="file" /></label>
<div class="col-md-6">
<input id="certFileI" name="certFileI" type="file" multiple="multiple"
style="width: 330px; display: none" />
<div class="input-group">
<input id="certFileInfo" name="certFileInfo" readonly="readonly"
data-msg-required=""
placeholder="<spring:message code="select_file"/>"
class="required form-control"
style="background-color: transparent" aria-required="true"
type="text" value="">
<div class="input-group-btn">
<a id="uploadCertFile" class="btn btn-default btn-search"
href="javascript:" style=""><i class="fa fa-search"></i></a>
</div>
<input id="certFile" name="certFile" type="hidden" value=""/>
</div>
</div>
<div id="certInfo"></div>
</div>
</div>
</div>
<div class="modal-footer" style="border-top:0px">
<button type="button" class="btn red" onclick="submitCertFrom()">
<spring:message code="ok" />
</button>
<button type="button" class="btn" data-dismiss="modal">
<spring:message code="close" />
</button>
</div>
</div>
</div>
</form>
</div>

View File

@@ -38,6 +38,17 @@
} }
} }
}); });
var addCertFile=function(obj){
if($(obj).attr("attribute") != null && $(obj).attr("attribute") != ''){
attribute=$(obj).attr("attribute");
}
$("#add_cert_modal").modal({
backdrop:"static",
keyboard:false,
show:true
});
}
</script> </script>
</head> </head>
<body> <body>
@@ -51,6 +62,12 @@
<i class="fa fa-plus"></i> <i class="fa fa-plus"></i>
<spring:message code="add"></spring:message></button> <spring:message code="add"></spring:message></button>
</shiro:hasPermission> </shiro:hasPermission>
<c:if test="${!hasBuiltIn}">
<button type="button" class="btn btn-primary"
onClick="addCertFile(this)">
<i class="fa fa-plus"></i>
<spring:message code="import_built_cert_file"></spring:message></button>
</c:if>
</div> </div>
<h3 class="page-title"> <h3 class="page-title">
@@ -460,6 +477,7 @@
</div> </div>
</div> </div>
</div> </div>
<!-- keyring cert配置新增 -->
<%@include file="/WEB-INF/views/cfg/intercept/strateagy/keyRingCertForm.jsp" %>
</body> </body>
</html> </html>

View File

@@ -540,7 +540,7 @@
</div> </div>
</div> </div>
<c:set var="trustedCertPath" value="/proxy/intercept/strateagy/trustedCertList?functionId=${cfg.functionId}"/> <c:set var="trustedCertPath" value="/proxy/intercept/strateagy/trustedCertList?functionId=${cfg.functionId}"/>
<!-- crl配置新增 --> <!-- truted cert配置新增 -->
<%@include file="/WEB-INF/views/cfg/intercept/strateagy/certForm.jsp" %> <%@include file="/WEB-INF/views/cfg/intercept/strateagy/certForm.jsp" %>
<%-- <%@include file="/WEB-INF/views/cfg/intercept/strateagy/crlForm.jsp" %> --%> <%-- <%@include file="/WEB-INF/views/cfg/intercept/strateagy/crlForm.jsp" %> --%>
</body> </body>