mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 12:56:28 +08:00
秘钥管理改造
This commit is contained in:
@@ -4,3 +4,4 @@
|
||||
- 运行`SopAdminServerApplication.java`
|
||||
- 访问:`http://localhost:8082`
|
||||
|
||||
登录账号:admin/123456
|
||||
|
@@ -8,29 +8,32 @@ import com.gitee.easyopen.doc.annotation.ApiDoc;
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField;
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocMethod;
|
||||
import com.gitee.easyopen.util.CopyUtil;
|
||||
import com.gitee.easyopen.util.KeyStore;
|
||||
import com.gitee.easyopen.util.RSAUtil;
|
||||
import com.gitee.fastmybatis.core.PageInfo;
|
||||
import com.gitee.fastmybatis.core.query.Query;
|
||||
import com.gitee.fastmybatis.core.util.MapperUtil;
|
||||
import com.gitee.sop.adminserver.api.IdParam;
|
||||
import com.gitee.sop.adminserver.api.isv.param.IsvInfoForm;
|
||||
import com.gitee.sop.adminserver.api.isv.param.IsvInfoFormAdd;
|
||||
import com.gitee.sop.adminserver.api.isv.param.IsvInfoFormUpdate;
|
||||
import com.gitee.sop.adminserver.api.isv.param.IsvKeysFormUpdate;
|
||||
import com.gitee.sop.adminserver.api.isv.param.IsvKeysGen;
|
||||
import com.gitee.sop.adminserver.api.isv.param.IsvPageParam;
|
||||
import com.gitee.sop.adminserver.api.isv.result.IsvFormVO;
|
||||
import com.gitee.sop.adminserver.api.isv.result.IsvVO;
|
||||
import com.gitee.sop.adminserver.api.isv.result.IsvDetailDTO;
|
||||
import com.gitee.sop.adminserver.api.isv.result.IsvInfoVO;
|
||||
import com.gitee.sop.adminserver.api.isv.result.IsvKeysGenVO;
|
||||
import com.gitee.sop.adminserver.api.isv.result.IsvKeysVO;
|
||||
import com.gitee.sop.adminserver.api.isv.result.RoleVO;
|
||||
import com.gitee.sop.adminserver.bean.ChannelMsg;
|
||||
import com.gitee.sop.adminserver.bean.ZookeeperContext;
|
||||
import com.gitee.sop.adminserver.common.BizException;
|
||||
import com.gitee.sop.adminserver.common.IdGen;
|
||||
import com.gitee.sop.adminserver.common.ZookeeperOperationException;
|
||||
import com.gitee.sop.adminserver.common.RSATool;
|
||||
import com.gitee.sop.adminserver.common.ZookeeperPathNotExistException;
|
||||
import com.gitee.sop.adminserver.entity.IsvInfo;
|
||||
import com.gitee.sop.adminserver.entity.IsvKeys;
|
||||
import com.gitee.sop.adminserver.entity.PermIsvRole;
|
||||
import com.gitee.sop.adminserver.entity.PermRole;
|
||||
import com.gitee.sop.adminserver.mapper.IsvInfoMapper;
|
||||
import com.gitee.sop.adminserver.mapper.IsvKeysMapper;
|
||||
import com.gitee.sop.adminserver.mapper.PermIsvRoleMapper;
|
||||
import com.gitee.sop.adminserver.mapper.PermRoleMapper;
|
||||
import com.gitee.sop.adminserver.service.RoutePermissionService;
|
||||
@@ -39,6 +42,7 @@ import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
@@ -57,6 +61,9 @@ public class IsvApi {
|
||||
@Autowired
|
||||
IsvInfoMapper isvInfoMapper;
|
||||
|
||||
@Autowired
|
||||
IsvKeysMapper isvKeysMapper;
|
||||
|
||||
@Autowired
|
||||
PermIsvRoleMapper permIsvRoleMapper;
|
||||
|
||||
@@ -71,20 +78,20 @@ public class IsvApi {
|
||||
@ApiDocField(name = "pageIndex", description = "第几页", dataType = DataType.INT, example = "1"),
|
||||
@ApiDocField(name = "pageSize", description = "每页几条数据", dataType = DataType.INT, example = "10"),
|
||||
@ApiDocField(name = "total", description = "每页几条数据", dataType = DataType.LONG, example = "100"),
|
||||
@ApiDocField(name = "rows", description = "数据", dataType = DataType.ARRAY, elementClass = IsvVO.class)
|
||||
@ApiDocField(name = "rows", description = "数据", dataType = DataType.ARRAY, elementClass = IsvInfoVO.class)
|
||||
})
|
||||
PageInfo<IsvVO> pageIsv(IsvPageParam param) {
|
||||
PageInfo<IsvInfoVO> pageIsv(IsvPageParam param) {
|
||||
Query query = Query.build(param);
|
||||
PageInfo<IsvInfo> pageInfo = MapperUtil.query(isvInfoMapper, query);
|
||||
List<IsvInfo> list = pageInfo.getList();
|
||||
|
||||
List<IsvVO> retList = list.stream()
|
||||
List<IsvInfoVO> retList = list.stream()
|
||||
.map(isvInfo -> {
|
||||
return buildIsvVO(isvInfo);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
PageInfo<IsvVO> pageInfoRet = new PageInfo<>();
|
||||
PageInfo<IsvInfoVO> pageInfoRet = new PageInfo<>();
|
||||
pageInfoRet.setTotal(pageInfo.getTotal());
|
||||
pageInfoRet.setList(retList);
|
||||
|
||||
@@ -93,16 +100,30 @@ public class IsvApi {
|
||||
|
||||
@Api(name = "isv.info.get")
|
||||
@ApiDocMethod(description = "获取isv")
|
||||
IsvVO getIsvVO(IdParam param) {
|
||||
IsvInfoVO getIsvVO(IdParam param) {
|
||||
IsvInfo isvInfo = isvInfoMapper.getById(param.getId());
|
||||
return buildIsvVO(isvInfo);
|
||||
}
|
||||
|
||||
private IsvVO buildIsvVO(IsvInfo isvInfo) {
|
||||
@Api(name = "isv.keys.get")
|
||||
@ApiDocMethod(description = "获取isv2")
|
||||
IsvKeysVO getIsvKeys(@NotBlank(message = "appKey不能为空")
|
||||
@ApiDocField(description = "appKey")
|
||||
String appKey) {
|
||||
IsvKeys isvKeys = isvKeysMapper.getByColumn("app_key", appKey);
|
||||
IsvKeysVO isvDetailVO = new IsvKeysVO();
|
||||
if (isvKeys != null) {
|
||||
CopyUtil.copyProperties(isvKeys, isvDetailVO);
|
||||
}
|
||||
isvDetailVO.setAppKey(appKey);
|
||||
return isvDetailVO;
|
||||
}
|
||||
|
||||
private IsvInfoVO buildIsvVO(IsvInfo isvInfo) {
|
||||
if (isvInfo == null) {
|
||||
return null;
|
||||
}
|
||||
IsvVO vo = new IsvVO();
|
||||
IsvInfoVO vo = new IsvInfoVO();
|
||||
CopyUtil.copyProperties(isvInfo, vo);
|
||||
vo.setRoleList(this.buildIsvRole(isvInfo));
|
||||
return vo;
|
||||
@@ -134,44 +155,57 @@ public class IsvApi {
|
||||
@ApiDocMethod(description = "添加isv")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addIsv(IsvInfoFormAdd param) throws Exception {
|
||||
if (isvInfoMapper.getByColumn("app_key", param.getAppKey()) != null) {
|
||||
throw new BizException("appKey已存在");
|
||||
}
|
||||
formatForm(param);
|
||||
String appKey = new SimpleDateFormat("yyyyMMdd").format(new Date()) + IdGen.nextId();
|
||||
IsvInfo rec = new IsvInfo();
|
||||
rec.setAppKey(appKey);
|
||||
CopyUtil.copyPropertiesIgnoreNull(param, rec);
|
||||
isvInfoMapper.saveIgnoreNull(rec);
|
||||
if (CollectionUtils.isNotEmpty(param.getRoleCode())) {
|
||||
this.saveIsvRole(rec, param.getRoleCode());
|
||||
}
|
||||
IsvKeysGenVO isvKeysGenVO = this.createIsvKeys();
|
||||
IsvKeys isvKeys = new IsvKeys();
|
||||
CopyUtil.copyPropertiesIgnoreNull(isvKeysGenVO, isvKeys);
|
||||
isvKeysMapper.saveIgnoreNull(isvKeys);
|
||||
|
||||
this.sendChannelMsg(rec);
|
||||
this.sendChannelMsg(rec.getAppKey());
|
||||
}
|
||||
|
||||
@Api(name = "isv.info.update")
|
||||
@ApiDocMethod(description = "修改isv")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateIsv(IsvInfoFormUpdate param) {
|
||||
formatForm(param);
|
||||
IsvInfo rec = isvInfoMapper.getById(param.getId());
|
||||
CopyUtil.copyPropertiesIgnoreNull(param, rec);
|
||||
isvInfoMapper.updateIgnoreNull(rec);
|
||||
this.saveIsvRole(rec, param.getRoleCode());
|
||||
|
||||
this.sendChannelMsg(rec);
|
||||
this.sendChannelMsg(rec.getAppKey());
|
||||
}
|
||||
|
||||
private void formatForm(IsvInfoForm form) {
|
||||
if (form.getSignType() == SIGN_TYPE_RSA2) {
|
||||
form.setSecret("");
|
||||
@Api(name = "isv.keys.update")
|
||||
@ApiDocMethod(description = "修改isv")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateIsvKeys(IsvKeysFormUpdate param) {
|
||||
IsvKeys isvKeys = isvKeysMapper.getByColumn("app_key", param.getAppKey());
|
||||
if (isvKeys == null) {
|
||||
isvKeys = new IsvKeys();
|
||||
CopyUtil.copyPropertiesIgnoreNull(param, isvKeys);
|
||||
isvKeysMapper.saveIgnoreNull(isvKeys);
|
||||
} else {
|
||||
form.setPubKey("");
|
||||
form.setPriKey("");
|
||||
CopyUtil.copyPropertiesIgnoreNull(param, isvKeys);
|
||||
isvKeysMapper.updateIgnoreNull(isvKeys);
|
||||
}
|
||||
|
||||
this.sendChannelMsg(isvKeys.getAppKey());
|
||||
}
|
||||
|
||||
private void sendChannelMsg(IsvInfo rec) {
|
||||
ChannelMsg channelMsg = new ChannelMsg("update", rec);
|
||||
private void sendChannelMsg(String appKey) {
|
||||
IsvDetailDTO isvDetail = isvInfoMapper.getIsvDetail(appKey);
|
||||
if (isvDetail == null) {
|
||||
return;
|
||||
}
|
||||
ChannelMsg channelMsg = new ChannelMsg("update", isvDetail);
|
||||
String path = ZookeeperContext.getIsvInfoChannelPath();
|
||||
String data = JSON.toJSONString(channelMsg);
|
||||
try {
|
||||
@@ -183,23 +217,41 @@ public class IsvApi {
|
||||
}
|
||||
}
|
||||
|
||||
@Api(name = "isv.form.gen")
|
||||
@ApiDocMethod(description = "isv表单内容一键生成")
|
||||
IsvFormVO createIsvForm() throws Exception {
|
||||
IsvFormVO isvFormVO = new IsvFormVO();
|
||||
String appKey = new SimpleDateFormat("yyyyMMdd").format(new Date()) + IdGen.nextId();
|
||||
private IsvKeysGenVO createIsvKeys() throws Exception {
|
||||
IsvKeysGenVO isvFormVO = new IsvKeysGenVO();
|
||||
String secret = IdGen.uuid();
|
||||
|
||||
isvFormVO.setAppKey(appKey);
|
||||
isvFormVO.setSecret(secret);
|
||||
|
||||
KeyStore keyStore = RSAUtil.createKeys();
|
||||
isvFormVO.setPubKey(keyStore.getPublicKey());
|
||||
isvFormVO.setPriKey(keyStore.getPrivateKey());
|
||||
RSATool rsaToolIsv = new RSATool(RSATool.KeyFormat.PKCS8, RSATool.KeyLength.LENGTH_2048);
|
||||
RSATool.KeyStore keyStoreIsv = rsaToolIsv.createKeys();
|
||||
isvFormVO.setPublicKeyIsv(keyStoreIsv.getPublicKey());
|
||||
isvFormVO.setPrivateKeyIsv(keyStoreIsv.getPrivateKey());
|
||||
|
||||
RSATool rsaToolPlatform = new RSATool(RSATool.KeyFormat.PKCS8, RSATool.KeyLength.LENGTH_2048);
|
||||
RSATool.KeyStore keyStorePlatform = rsaToolPlatform.createKeys();
|
||||
isvFormVO.setPublicKeyPlatform(keyStorePlatform.getPublicKey());
|
||||
isvFormVO.setPrivateKeyPlatform(keyStorePlatform.getPrivateKey());
|
||||
return isvFormVO;
|
||||
}
|
||||
|
||||
@Api(name = "isv.keys.gen")
|
||||
@ApiDocMethod(description = "生成公私钥")
|
||||
RSATool.KeyStore createPubPriKey(IsvKeysGen param) throws Exception {
|
||||
RSATool.KeyFormat format = RSATool.KeyFormat.PKCS8;
|
||||
Byte keyFormat = param.getKeyFormat();
|
||||
if (keyFormat != null && keyFormat == 2) {
|
||||
format = RSATool.KeyFormat.PKCS1;
|
||||
}
|
||||
RSATool rsaTool = new RSATool(format, RSATool.KeyLength.LENGTH_2048);
|
||||
return rsaTool.createKeys();
|
||||
}
|
||||
|
||||
@Api(name = "isv.secret.gen")
|
||||
@ApiDocMethod(description = "生成MD秘钥")
|
||||
String createSecret() throws Exception {
|
||||
return IdGen.uuid();
|
||||
}
|
||||
|
||||
void saveIsvRole(IsvInfo isvInfo, List<String> roleCodeList) {
|
||||
Query query = new Query();
|
||||
|
@@ -2,9 +2,7 @@ package com.gitee.sop.adminserver.api.isv.param;
|
||||
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -14,22 +12,6 @@ import java.util.List;
|
||||
@Data
|
||||
public class IsvInfoForm {
|
||||
|
||||
@NotNull(message = "signType不能为null")
|
||||
private Byte signType;
|
||||
|
||||
/** secret, 数据库字段:secret */
|
||||
@ApiDocField(description = "secret")
|
||||
@Length(max = 100,message = "secret长度不能超过100")
|
||||
private String secret = "";
|
||||
|
||||
/** 公钥, 数据库字段:pub_key */
|
||||
@ApiDocField(description = "pubKey")
|
||||
private String pubKey;
|
||||
|
||||
/** 私钥, 数据库字段:pri_key */
|
||||
@ApiDocField(description = "priKey")
|
||||
private String priKey;
|
||||
|
||||
/** 0启用,1禁用, 数据库字段:status */
|
||||
@ApiDocField(description = "状态:0:启用,1:禁用")
|
||||
private Byte status = 0;
|
||||
|
@@ -1,11 +1,7 @@
|
||||
package com.gitee.sop.adminserver.api.isv.param;
|
||||
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
@@ -13,9 +9,4 @@ import javax.validation.constraints.NotBlank;
|
||||
@Getter
|
||||
@Setter
|
||||
public class IsvInfoFormAdd extends IsvInfoForm {
|
||||
/** appKey, 数据库字段:app_key */
|
||||
@ApiDocField(description = "appKey", required = true)
|
||||
@NotBlank(message = "appKey不能为空")
|
||||
@Length(max = 100,message = "appKey长度不能超过100")
|
||||
private String appKey;
|
||||
}
|
||||
|
@@ -0,0 +1,52 @@
|
||||
package com.gitee.sop.adminserver.api.isv.param;
|
||||
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class IsvKeysFormUpdate {
|
||||
/** appKey, 数据库字段:app_key */
|
||||
@ApiDocField(description = "appKey", example = "aaaa")
|
||||
@NotBlank(message = "appKey不能为空")
|
||||
@Length(max = 100,message = "appKey长度不能超过100")
|
||||
private String appKey;
|
||||
|
||||
/** secret, 数据库字段:secret */
|
||||
@ApiDocField(description = "secret", example = "bbbb")
|
||||
private String secret;
|
||||
|
||||
/** 秘钥格式,1:PKCS8(JAVA适用),2:PKCS1(非JAVA适用), 数据库字段:key_format */
|
||||
@ApiDocField(description = "秘钥格式,1:PKCS8(JAVA适用),2:PKCS1(非JAVA适用)", example = "1")
|
||||
@Min(value = 1, message = "秘钥格式错误")
|
||||
@Max(value = 2, message = "秘钥格式错误")
|
||||
private Byte keyFormat;
|
||||
|
||||
/** 开发者生成的公钥, 数据库字段:public_key_isv */
|
||||
@ApiDocField(description = "开发者生成的公钥")
|
||||
private String publicKeyIsv;
|
||||
|
||||
/** 开发者生成的私钥(交给开发者), 数据库字段:private_key_isv */
|
||||
@ApiDocField(description = "开发者生成的私钥")
|
||||
private String privateKeyIsv;
|
||||
|
||||
/** 平台生成的公钥(交给开发者), 数据库字段:public_key_platform */
|
||||
@ApiDocField(description = "平台生成的公钥")
|
||||
private String publicKeyPlatform;
|
||||
|
||||
/** 平台生成的私钥, 数据库字段:private_key_platform */
|
||||
@ApiDocField(description = "平台生成的私钥")
|
||||
private String privateKeyPlatform;
|
||||
|
||||
@ApiDocField(description = "签名类型:1:RSA2,2:MD5")
|
||||
@NotNull(message = "signType不能为空")
|
||||
private Byte signType;
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
package com.gitee.sop.adminserver.api.isv.param;
|
||||
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class IsvKeysGen {
|
||||
@ApiDocField(description = "秘钥格式,1:PKCS8(JAVA适用),2:PKCS1(非JAVA适用)", example = "1")
|
||||
@Min(value = 1, message = "秘钥格式错误")
|
||||
@Max(value = 2, message = "秘钥格式错误")
|
||||
private Byte keyFormat;
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
package com.gitee.sop.adminserver.api.isv.result;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class IsvAppKeyGenVO {
|
||||
private String appKey;
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
package com.gitee.sop.adminserver.api.isv.result;
|
||||
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class IsvDetailDTO {
|
||||
|
||||
/** appKey, 数据库字段:app_key */
|
||||
@ApiDocField(description = "appKey", example = "aaaa")
|
||||
private String appKey;
|
||||
|
||||
/** 0启用,1禁用, 数据库字段:status */
|
||||
@ApiDocField(description = "状态:0启用,1禁用")
|
||||
private Byte status;
|
||||
|
||||
// keys
|
||||
|
||||
/** secret, 数据库字段:secret */
|
||||
@ApiDocField(description = "secret", example = "bbbb")
|
||||
private String secret;
|
||||
|
||||
/** 开发者生成的公钥, 数据库字段:public_key_isv */
|
||||
private String publicKeyIsv;
|
||||
|
||||
/** 平台生成的私钥, 数据库字段:private_key_platform */
|
||||
private String privateKeyPlatform;
|
||||
|
||||
@ApiDocField(description = "签名类型:1:RSA2,2:MD5")
|
||||
private Byte signType;
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
package com.gitee.sop.adminserver.api.isv.result;
|
||||
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class IsvFormVO {
|
||||
@ApiDocField(description = "appKey", example = "aaaa")
|
||||
private String appKey;
|
||||
|
||||
@ApiDocField(description = "secret", example = "bbbb")
|
||||
private String secret;
|
||||
|
||||
@ApiDocField(description = "pubKey")
|
||||
private String pubKey;
|
||||
|
||||
@ApiDocField(description = "priKey")
|
||||
private String priKey;
|
||||
|
||||
}
|
@@ -10,7 +10,7 @@ import java.util.List;
|
||||
* @author thc
|
||||
*/
|
||||
@Data
|
||||
public class IsvVO {
|
||||
public class IsvInfoVO {
|
||||
/** 数据库字段:id */
|
||||
@ApiDocField(description = "id", example = "1")
|
||||
private Long id;
|
||||
@@ -19,18 +19,6 @@ public class IsvVO {
|
||||
@ApiDocField(description = "appKey", example = "aaaa")
|
||||
private String appKey;
|
||||
|
||||
/** secret, 数据库字段:secret */
|
||||
@ApiDocField(description = "secret", example = "bbbb")
|
||||
private String secret;
|
||||
|
||||
/** 公钥, 数据库字段:pub_key */
|
||||
@ApiDocField(description = "pubKey")
|
||||
private String pubKey;
|
||||
|
||||
/** 私钥, 数据库字段:pri_key */
|
||||
@ApiDocField(description = "priKey")
|
||||
private String priKey;
|
||||
|
||||
/** 0启用,1禁用, 数据库字段:status */
|
||||
@ApiDocField(description = "状态:0启用,1禁用")
|
||||
private Byte status;
|
@@ -0,0 +1,25 @@
|
||||
package com.gitee.sop.adminserver.api.isv.result;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class IsvKeysGenVO {
|
||||
/** secret, 数据库字段:secret */
|
||||
private String secret;
|
||||
|
||||
/** 开发者生成的公钥, 数据库字段:public_key_isv */
|
||||
private String publicKeyIsv;
|
||||
|
||||
/** 开发者生成的私钥(交给开发者), 数据库字段:private_key_isv */
|
||||
private String privateKeyIsv;
|
||||
|
||||
/** 平台生成的公钥(交给开发者), 数据库字段:public_key_platform */
|
||||
private String publicKeyPlatform;
|
||||
|
||||
/** 平台生成的私钥, 数据库字段:private_key_platform */
|
||||
private String privateKeyPlatform;
|
||||
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
package com.gitee.sop.adminserver.api.isv.result;
|
||||
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author thc
|
||||
*/
|
||||
@Data
|
||||
public class IsvKeysVO {
|
||||
|
||||
/** appKey, 数据库字段:app_key */
|
||||
@ApiDocField(description = "appKey", example = "aaaa")
|
||||
private String appKey;
|
||||
|
||||
/** secret, 数据库字段:secret */
|
||||
@ApiDocField(description = "secret", example = "bbbb")
|
||||
private String secret;
|
||||
|
||||
/** 秘钥格式,1:PKCS8(JAVA适用),2:PKCS1(非JAVA适用), 数据库字段:key_format */
|
||||
private Byte keyFormat = 1;
|
||||
|
||||
/** 开发者生成的公钥, 数据库字段:public_key_isv */
|
||||
private String publicKeyIsv;
|
||||
|
||||
/** 开发者生成的私钥(交给开发者), 数据库字段:private_key_isv */
|
||||
private String privateKeyIsv;
|
||||
|
||||
/** 平台生成的公钥(交给开发者), 数据库字段:public_key_platform */
|
||||
private String publicKeyPlatform;
|
||||
|
||||
/** 平台生成的私钥, 数据库字段:private_key_platform */
|
||||
private String privateKeyPlatform;
|
||||
|
||||
@ApiDocField(description = "签名类型:1:RSA2,2:MD5")
|
||||
private Byte signType = 1;
|
||||
|
||||
}
|
@@ -0,0 +1,410 @@
|
||||
package com.gitee.sop.adminserver.common;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
import org.bouncycastle.asn1.ASN1Primitive;
|
||||
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
|
||||
/**
|
||||
* RSA加解密工具<br>
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
public class RSATool {
|
||||
public static String RSA_ALGORITHM = "RSA";
|
||||
|
||||
private KeyFormat keyFormat;
|
||||
private KeyLength keyLength;
|
||||
|
||||
public RSATool(KeyFormat keyFormat, KeyLength keyLength) {
|
||||
this.keyFormat = keyFormat;
|
||||
this.keyLength = keyLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建公钥私钥
|
||||
*
|
||||
* @return 返回公私钥对
|
||||
* @throws Exception
|
||||
*/
|
||||
public KeyStore createKeys() throws Exception {
|
||||
KeyPairGenerator keyPairGeno = KeyPairGenerator.getInstance(RSA_ALGORITHM);
|
||||
keyPairGeno.initialize(keyLength.getLength());
|
||||
KeyPair keyPair = keyPairGeno.generateKeyPair();
|
||||
|
||||
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
|
||||
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
|
||||
|
||||
KeyStore keyStore = new KeyStore();
|
||||
if (this.keyFormat == KeyFormat.PKCS1) {
|
||||
keyStore.setPublicKey(Base64.encodeBase64String(publicKey.getEncoded()));
|
||||
keyStore.setPrivateKey(convertPkcs8ToPkcs1(privateKey.getEncoded()));
|
||||
} else {
|
||||
keyStore.setPublicKey(Base64.encodeBase64String(publicKey.getEncoded()));
|
||||
keyStore.setPrivateKey(Base64.encodeBase64String(privateKey.getEncoded()));
|
||||
}
|
||||
return keyStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取公钥对象
|
||||
*
|
||||
* @param pubKeyData 公钥
|
||||
* @return 返回公钥对象
|
||||
* @throws Exception
|
||||
*/
|
||||
public RSAPublicKey getPublicKey(byte[] pubKeyData) throws Exception {
|
||||
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubKeyData);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
|
||||
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取公钥对象
|
||||
*
|
||||
* @param pubKey 公钥
|
||||
* @return 返回私钥对象
|
||||
* @throws Exception
|
||||
*/
|
||||
public RSAPublicKey getPublicKey(String pubKey) throws Exception {
|
||||
return getPublicKey(Base64.decodeBase64(pubKey));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取私钥对象
|
||||
*
|
||||
* @param priKey 私钥
|
||||
* @return 私钥对象
|
||||
* @throws Exception
|
||||
*/
|
||||
public RSAPrivateKey getPrivateKey(String priKey) throws Exception {
|
||||
return getPrivateKey(Base64.decodeBase64(priKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过私钥byte[]将公钥还原,适用于RSA算法
|
||||
*
|
||||
* @param keyBytes
|
||||
* @return 返回私钥
|
||||
* @throws Exception
|
||||
*/
|
||||
public RSAPrivateKey getPrivateKey(byte[] keyBytes) throws Exception {
|
||||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
|
||||
return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 公钥加密
|
||||
*
|
||||
* @param data 待加密内容
|
||||
* @param publicKey 公钥
|
||||
* @return 返回密文
|
||||
* @throws Exception
|
||||
*/
|
||||
public String encryptByPublicKey(String data, RSAPublicKey publicKey) throws Exception {
|
||||
Cipher cipher = Cipher.getInstance(keyFormat.getCipherAlgorithm());
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
// 模长
|
||||
int key_len = publicKey.getModulus().bitLength() / 8;
|
||||
// 加密数据长度 <= 模长-11
|
||||
String[] datas = splitString(data, key_len - 11);
|
||||
String mi = "";
|
||||
// 如果明文长度大于模长-11则要分组加密
|
||||
for (String s : datas) {
|
||||
mi += bcd2Str(cipher.doFinal(s.getBytes()));
|
||||
}
|
||||
return mi;
|
||||
}
|
||||
|
||||
public String encryptByPrivateKey(String data, String privateKey) throws Exception {
|
||||
return encryptByPrivateKey(data, getPrivateKey(privateKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* 私钥加密
|
||||
*
|
||||
* @param data 待加密数据
|
||||
* @param privateKey 私钥
|
||||
* @return 返回密文
|
||||
* @throws Exception
|
||||
*/
|
||||
public String encryptByPrivateKey(String data, RSAPrivateKey privateKey) throws Exception {
|
||||
Cipher cipher = Cipher.getInstance(keyFormat.getCipherAlgorithm());
|
||||
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
|
||||
// 模长
|
||||
int key_len = privateKey.getModulus().bitLength() / 8;
|
||||
// 加密数据长度 <= 模长-11
|
||||
String[] datas = splitString(data, key_len - 11);
|
||||
String mi = "";
|
||||
// 如果明文长度大于模长-11则要分组加密
|
||||
for (String s : datas) {
|
||||
mi += bcd2Str(cipher.doFinal(s.getBytes()));
|
||||
}
|
||||
return mi;
|
||||
}
|
||||
|
||||
public String decryptByPrivateKey(String data, String privateKey) throws Exception {
|
||||
return decryptByPrivateKey(data, getPrivateKey(privateKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* 私钥解密
|
||||
*
|
||||
* @param data 待解密内容
|
||||
* @param privateKey 私钥
|
||||
* @return 返回明文
|
||||
* @throws Exception
|
||||
*/
|
||||
public String decryptByPrivateKey(String data, RSAPrivateKey privateKey) throws Exception {
|
||||
Cipher cipher = Cipher.getInstance(keyFormat.getCipherAlgorithm());
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
// 模长
|
||||
int key_len = privateKey.getModulus().bitLength() / 8;
|
||||
byte[] bytes = data.getBytes();
|
||||
byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
|
||||
// 如果密文长度大于模长则要分组解密
|
||||
String ming = "";
|
||||
byte[][] arrays = splitArray(bcd, key_len);
|
||||
for (byte[] arr : arrays) {
|
||||
ming += new String(cipher.doFinal(arr));
|
||||
}
|
||||
return ming;
|
||||
}
|
||||
|
||||
/**
|
||||
* 公钥解密
|
||||
*
|
||||
* @param data 待解密内容
|
||||
* @param rsaPublicKey 公钥
|
||||
* @return 返回明文
|
||||
* @throws Exception
|
||||
*/
|
||||
public String decryptByPublicKey(String data, RSAPublicKey rsaPublicKey) throws Exception {
|
||||
Cipher cipher = Cipher.getInstance(keyFormat.getCipherAlgorithm());
|
||||
cipher.init(Cipher.DECRYPT_MODE, rsaPublicKey);
|
||||
// 模长
|
||||
int key_len = rsaPublicKey.getModulus().bitLength() / 8;
|
||||
byte[] bytes = data.getBytes();
|
||||
byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
|
||||
// 如果密文长度大于模长则要分组解密
|
||||
String ming = "";
|
||||
byte[][] arrays = splitArray(bcd, key_len);
|
||||
for (byte[] arr : arrays) {
|
||||
ming += new String(cipher.doFinal(arr));
|
||||
}
|
||||
return ming;
|
||||
}
|
||||
|
||||
public static String convertPkcs8ToPkcs1(byte[] privateKeyData) throws Exception{
|
||||
PrivateKeyInfo pkInfo = PrivateKeyInfo.getInstance(privateKeyData);
|
||||
ASN1Encodable encodable = pkInfo.parsePrivateKey();
|
||||
ASN1Primitive primitive = encodable.toASN1Primitive();
|
||||
byte[] privateKeyPKCS1 = primitive.getEncoded();
|
||||
return Base64.encodeBase64String(privateKeyPKCS1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ASCII码转BCD码
|
||||
*/
|
||||
public static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
|
||||
byte[] bcd = new byte[asc_len / 2];
|
||||
int j = 0;
|
||||
for (int i = 0; i < (asc_len + 1) / 2; i++) {
|
||||
bcd[i] = asc_to_bcd(ascii[j++]);
|
||||
bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++]) & 0xff) + (bcd[i] << 4));
|
||||
}
|
||||
return bcd;
|
||||
}
|
||||
|
||||
public static byte asc_to_bcd(byte asc) {
|
||||
byte bcd;
|
||||
|
||||
if ((asc >= '0') && (asc <= '9')) {
|
||||
bcd = (byte) (asc - '0');
|
||||
} else if ((asc >= 'A') && (asc <= 'F')) {
|
||||
bcd = (byte) (asc - 'A' + 10);
|
||||
} else if ((asc >= 'a') && (asc <= 'f')) {
|
||||
bcd = (byte) (asc - 'a' + 10);
|
||||
} else {
|
||||
bcd = (byte) (asc - 48);
|
||||
}
|
||||
return bcd;
|
||||
}
|
||||
|
||||
/**
|
||||
* BCD转字符串
|
||||
*/
|
||||
public String bcd2Str(byte[] bytes) {
|
||||
char[] temp = new char[bytes.length * 2];
|
||||
char val;
|
||||
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
|
||||
temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
|
||||
|
||||
val = (char) (bytes[i] & 0x0f);
|
||||
temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
|
||||
}
|
||||
return new String(temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拆分字符串
|
||||
*/
|
||||
public String[] splitString(String string, int len) {
|
||||
int x = string.length() / len;
|
||||
int y = string.length() % len;
|
||||
int z = 0;
|
||||
if (y != 0) {
|
||||
z = 1;
|
||||
}
|
||||
String[] strings = new String[x + z];
|
||||
String str = "";
|
||||
for (int i = 0; i < x + z; i++) {
|
||||
if (i == x + z - 1 && y != 0) {
|
||||
str = string.substring(i * len, i * len + y);
|
||||
} else {
|
||||
str = string.substring(i * len, i * len + len);
|
||||
}
|
||||
strings[i] = str;
|
||||
}
|
||||
return strings;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拆分数组
|
||||
*/
|
||||
public byte[][] splitArray(byte[] data, int len) {
|
||||
int x = data.length / len;
|
||||
int y = data.length % len;
|
||||
int z = 0;
|
||||
if (y != 0) {
|
||||
z = 1;
|
||||
}
|
||||
byte[][] arrays = new byte[x + z][];
|
||||
byte[] arr;
|
||||
for (int i = 0; i < x + z; i++) {
|
||||
arr = new byte[len];
|
||||
if (i == x + z - 1 && y != 0) {
|
||||
System.arraycopy(data, i * len, arr, 0, y);
|
||||
} else {
|
||||
System.arraycopy(data, i * len, arr, 0, len);
|
||||
}
|
||||
arrays[i] = arr;
|
||||
}
|
||||
return arrays;
|
||||
}
|
||||
|
||||
public enum KeyLength {
|
||||
LENGTH_1024(1024), LENGTH_2048(2048);
|
||||
private int length;
|
||||
|
||||
KeyLength(int length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
public static class KeyStore {
|
||||
private String publicKey;
|
||||
private String privateKey;
|
||||
|
||||
public String getPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
public void setPublicKey(String publicKey) {
|
||||
this.publicKey = publicKey;
|
||||
}
|
||||
|
||||
public String getPrivateKey() {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
public void setPrivateKey(String privateKey) {
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
}
|
||||
|
||||
public enum KeyFormat {
|
||||
PKCS1("RSA/ECB/PKCS1Padding"), PKCS8("RSA");
|
||||
private String cipherAlgorithm;
|
||||
|
||||
KeyFormat(String cipherAlgorithm) {
|
||||
this.cipherAlgorithm = cipherAlgorithm;
|
||||
}
|
||||
|
||||
public String getCipherAlgorithm() {
|
||||
return cipherAlgorithm;
|
||||
}
|
||||
}
|
||||
|
||||
public KeyFormat getKeyFormat() {
|
||||
return keyFormat;
|
||||
}
|
||||
|
||||
public KeyLength getKeyLength() {
|
||||
return keyLength;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------ Test ------------
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
RSATool rsa_pkcs8_1024 = new RSATool(KeyFormat.PKCS8, KeyLength.LENGTH_1024);
|
||||
RSATool rsa_pkcs8_2048 = new RSATool(KeyFormat.PKCS8, KeyLength.LENGTH_2048);
|
||||
|
||||
doTest(rsa_pkcs8_1024);
|
||||
doTest(rsa_pkcs8_2048);
|
||||
|
||||
// PKCS在Java环境无法测试,可以生成一对,到非java平台测试,如C#
|
||||
}
|
||||
|
||||
private static void doTest(RSATool rsaTool) throws Exception {
|
||||
System.out.println("秘钥格式:" + rsaTool.keyFormat.name() + ", 秘钥长度:" + rsaTool.keyLength.getLength());
|
||||
KeyStore keys = rsaTool.createKeys();
|
||||
String pubKey = keys.getPublicKey();
|
||||
System.out.println("pubKey:");
|
||||
System.out.println(pubKey);
|
||||
String priKey = keys.getPrivateKey();
|
||||
System.out.println("priKey:");
|
||||
System.out.println(priKey);
|
||||
System.out.println("--------");
|
||||
|
||||
String ming = "你好,abc123~!@=";
|
||||
// 用公钥加密
|
||||
String mi = rsaTool.encryptByPublicKey(ming, rsaTool.getPublicKey(pubKey));
|
||||
System.out.println("mi : " + mi);
|
||||
// 用私钥解密
|
||||
String ming2 = rsaTool.decryptByPrivateKey(mi, rsaTool.getPrivateKey(priKey));
|
||||
System.out.println("ming : " + ming2 + ", 结果:" + ming2.equals(ming));
|
||||
|
||||
// 用私钥加密
|
||||
String mi2 = rsaTool.encryptByPrivateKey(ming, rsaTool.getPrivateKey(priKey));
|
||||
|
||||
System.out.println("mi2 : " + mi2);
|
||||
// 用公钥解密
|
||||
String ming3 = rsaTool.decryptByPublicKey(mi2, rsaTool.getPublicKey(pubKey));
|
||||
System.out.println("ming3 : " + ming3 + ", 结果:" + ming3.equals(ming));
|
||||
System.out.println("---------------------");
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
@@ -2,13 +2,13 @@ package com.gitee.sop.adminserver.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
@@ -19,7 +19,7 @@ import javax.persistence.Table;
|
||||
*/
|
||||
@Table(name = "admin_user_info")
|
||||
@Data
|
||||
public class AdminUserInfo {
|
||||
public class AdminUserInfo implements Serializable {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
|
@@ -28,21 +28,9 @@ public class IsvInfo {
|
||||
/** appKey, 数据库字段:app_key */
|
||||
private String appKey;
|
||||
|
||||
/** secret, 数据库字段:secret */
|
||||
private String secret;
|
||||
|
||||
/** 公钥, 数据库字段:pub_key */
|
||||
private String pubKey;
|
||||
|
||||
/** 私钥, 数据库字段:pri_key */
|
||||
private String priKey;
|
||||
|
||||
/** 1启用,2禁用, 数据库字段:status */
|
||||
private Byte status;
|
||||
|
||||
/** 1:RSA2,2:MD5, 数据库字段:sign_type */
|
||||
private Byte signType;
|
||||
|
||||
/** 数据库字段:gmt_create */
|
||||
private Date gmtCreate;
|
||||
|
||||
|
@@ -0,0 +1,57 @@
|
||||
package com.gitee.sop.adminserver.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 表名:isv_keys
|
||||
* 备注:ISV秘钥
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@Table(name = "isv_keys")
|
||||
@Data
|
||||
public class IsvKeys {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
/** 数据库字段:id */
|
||||
private Long id;
|
||||
|
||||
/** 数据库字段:app_key */
|
||||
private String appKey;
|
||||
|
||||
/** 1:RSA2,2:MD5, 数据库字段:sign_type */
|
||||
private Byte signType;
|
||||
|
||||
/** isv_info.sign_type=2时使用, 数据库字段:secret */
|
||||
private String secret;
|
||||
|
||||
/** 秘钥格式,1:PKCS8(JAVA适用),2:PKCS1(非JAVA适用), 数据库字段:key_format */
|
||||
private Byte keyFormat;
|
||||
|
||||
/** 开发者生成的公钥, 数据库字段:public_key_isv */
|
||||
private String publicKeyIsv;
|
||||
|
||||
/** 开发者生成的私钥(交给开发者), 数据库字段:private_key_isv */
|
||||
private String privateKeyIsv;
|
||||
|
||||
/** 平台生成的公钥(交给开发者), 数据库字段:public_key_platform */
|
||||
private String publicKeyPlatform;
|
||||
|
||||
/** 平台生成的私钥, 数据库字段:private_key_platform */
|
||||
private String privateKeyPlatform;
|
||||
|
||||
/** 数据库字段:gmt_create */
|
||||
private Date gmtCreate;
|
||||
|
||||
/** 数据库字段:gmt_modified */
|
||||
private Date gmtModified;
|
||||
}
|
@@ -2,11 +2,29 @@ package com.gitee.sop.adminserver.mapper;
|
||||
|
||||
import com.gitee.fastmybatis.core.mapper.CrudMapper;
|
||||
|
||||
import com.gitee.sop.adminserver.api.isv.result.IsvDetailDTO;
|
||||
import com.gitee.sop.adminserver.entity.IsvInfo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface IsvInfoMapper extends CrudMapper<IsvInfo, Long> {
|
||||
|
||||
@Select("SELECT " +
|
||||
" t.app_key appKey " +
|
||||
" ,t.status " +
|
||||
" ,t2.sign_type signType " +
|
||||
" ,t2.secret " +
|
||||
" ,t2.public_key_isv publicKeyIsv " +
|
||||
" ,t2.private_key_isv privateKeyIsv " +
|
||||
" ,t2.public_key_platform publicKeyPlatform " +
|
||||
" ,t2.private_key_platform privateKeyPlatform " +
|
||||
"FROM isv_info t " +
|
||||
"INNER JOIN isv_keys t2 ON t.app_key = t2.app_key " +
|
||||
"WHERE t.app_key = #{appKey}")
|
||||
IsvDetailDTO getIsvDetail(@Param("appKey") String appKey);
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,12 @@
|
||||
package com.gitee.sop.adminserver.mapper;
|
||||
|
||||
import com.gitee.fastmybatis.core.mapper.CrudMapper;
|
||||
|
||||
import com.gitee.sop.adminserver.entity.IsvKeys;
|
||||
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface IsvKeysMapper extends CrudMapper<IsvKeys, Long> {
|
||||
}
|
@@ -1 +1 @@
|
||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=favicon.ico><title>SOP Admin</title><link href=static/css/chunk-elementUI.81cf475c.css rel=stylesheet><link href=static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=static/css/app.4f0872ef.css rel=stylesheet></head><body><noscript><strong>We're sorry but SOP Admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function t(t){for(var r,o,c=t[0],i=t[1],f=t[2],l=0,s=[];l<c.length;l++)o=c[l],u[o]&&s.push(u[o][0]),u[o]=0;for(r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r]);d&&d(t);while(s.length)s.shift()();return a.push.apply(a,f||[]),n()}function n(){for(var e,t=0;t<a.length;t++){for(var n=a[t],r=!0,o=1;o<n.length;o++){var c=n[o];0!==u[c]&&(r=!1)}r&&(a.splice(t--,1),e=i(i.s=n[0]))}return e}var r={},o={runtime:0},u={runtime:0},a=[];function c(e){return i.p+"static/js/"+({}[e]||e)+"."+{"chunk-238a81e9":"5955f13d","chunk-2d221836":"574c9ab6","chunk-2d22c2e3":"46f37153","chunk-37401378":"4e39ec9b","chunk-4a59cbe4":"b5e74cc4","chunk-50417551":"ea8ad933","chunk-6a68a33e":"f59ae895","chunk-ea2e58a4":"f3f85b0e"}[e]+".js"}function i(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,i),n.l=!0,n.exports}i.e=function(e){var t=[],n={"chunk-238a81e9":1,"chunk-37401378":1,"chunk-50417551":1,"chunk-6a68a33e":1,"chunk-ea2e58a4":1};o[e]?t.push(o[e]):0!==o[e]&&n[e]&&t.push(o[e]=new Promise(function(t,n){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-238a81e9":"e8e2beee","chunk-2d221836":"31d6cfe0","chunk-2d22c2e3":"31d6cfe0","chunk-37401378":"a43114f3","chunk-4a59cbe4":"31d6cfe0","chunk-50417551":"8bd9f4f4","chunk-6a68a33e":"3b12267b","chunk-ea2e58a4":"d10599db"}[e]+".css",u=i.p+r,a=document.getElementsByTagName("link"),c=0;c<a.length;c++){var f=a[c],l=f.getAttribute("data-href")||f.getAttribute("href");if("stylesheet"===f.rel&&(l===r||l===u))return t()}var s=document.getElementsByTagName("style");for(c=0;c<s.length;c++){f=s[c],l=f.getAttribute("data-href");if(l===r||l===u)return t()}var d=document.createElement("link");d.rel="stylesheet",d.type="text/css",d.onload=t,d.onerror=function(t){var r=t&&t.target&&t.target.src||u,a=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");a.code="CSS_CHUNK_LOAD_FAILED",a.request=r,delete o[e],d.parentNode.removeChild(d),n(a)},d.href=u;var h=document.getElementsByTagName("head")[0];h.appendChild(d)}).then(function(){o[e]=0}));var r=u[e];if(0!==r)if(r)t.push(r[2]);else{var a=new Promise(function(t,n){r=u[e]=[t,n]});t.push(r[2]=a);var f,l=document.createElement("script");l.charset="utf-8",l.timeout=120,i.nc&&l.setAttribute("nonce",i.nc),l.src=c(e),f=function(t){l.onerror=l.onload=null,clearTimeout(s);var n=u[e];if(0!==n){if(n){var r=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src,a=new Error("Loading chunk "+e+" failed.\n("+r+": "+o+")");a.type=r,a.request=o,n[1](a)}u[e]=void 0}};var s=setTimeout(function(){f({type:"timeout",target:l})},12e4);l.onerror=l.onload=f,document.head.appendChild(l)}return Promise.all(t)},i.m=e,i.c=r,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)i.d(n,r,function(t){return e[t]}.bind(null,r));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i.oe=function(e){throw console.error(e),e};var f=window["webpackJsonp"]=window["webpackJsonp"]||[],l=f.push.bind(f);f.push=t,f=f.slice();for(var s=0;s<f.length;s++)t(f[s]);var d=l;n()})([]);</script><script src=static/js/chunk-elementUI.8ebdfbab.js></script><script src=static/js/chunk-libs.9cf9cc40.js></script><script src=static/js/app.3e92351d.js></script></body></html>
|
||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=favicon.ico><title>SOP Admin</title><link href=static/css/chunk-elementUI.81cf475c.css rel=stylesheet><link href=static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=static/css/app.4f0872ef.css rel=stylesheet></head><body><noscript><strong>We're sorry but SOP Admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function t(t){for(var r,c,a=t[0],i=t[1],f=t[2],l=0,h=[];l<a.length;l++)c=a[l],u[c]&&h.push(u[c][0]),u[c]=0;for(r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r]);s&&s(t);while(h.length)h.shift()();return o.push.apply(o,f||[]),n()}function n(){for(var e,t=0;t<o.length;t++){for(var n=o[t],r=!0,c=1;c<n.length;c++){var a=n[c];0!==u[a]&&(r=!1)}r&&(o.splice(t--,1),e=i(i.s=n[0]))}return e}var r={},c={runtime:0},u={runtime:0},o=[];function a(e){return i.p+"static/js/"+({}[e]||e)+"."+{"chunk-238a81e9":"5955f13d","chunk-25908fca":"29365d11","chunk-29e7142c":"994a3ac0","chunk-2d22c2e3":"46f37153","chunk-37401378":"4e39ec9b","chunk-4a59cbe4":"b5e74cc4","chunk-5f00e420":"5e409513","chunk-6a68a33e":"f59ae895","chunk-73b2dcec":"37433095"}[e]+".js"}function i(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,i),n.l=!0,n.exports}i.e=function(e){var t=[],n={"chunk-238a81e9":1,"chunk-25908fca":1,"chunk-29e7142c":1,"chunk-37401378":1,"chunk-5f00e420":1,"chunk-6a68a33e":1,"chunk-73b2dcec":1};c[e]?t.push(c[e]):0!==c[e]&&n[e]&&t.push(c[e]=new Promise(function(t,n){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-238a81e9":"e8e2beee","chunk-25908fca":"89ab33e8","chunk-29e7142c":"d10599db","chunk-2d22c2e3":"31d6cfe0","chunk-37401378":"a43114f3","chunk-4a59cbe4":"31d6cfe0","chunk-5f00e420":"aeebecd4","chunk-6a68a33e":"3b12267b","chunk-73b2dcec":"99cf6327"}[e]+".css",u=i.p+r,o=document.getElementsByTagName("link"),a=0;a<o.length;a++){var f=o[a],l=f.getAttribute("data-href")||f.getAttribute("href");if("stylesheet"===f.rel&&(l===r||l===u))return t()}var h=document.getElementsByTagName("style");for(a=0;a<h.length;a++){f=h[a],l=f.getAttribute("data-href");if(l===r||l===u)return t()}var s=document.createElement("link");s.rel="stylesheet",s.type="text/css",s.onload=t,s.onerror=function(t){var r=t&&t.target&&t.target.src||u,o=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");o.code="CSS_CHUNK_LOAD_FAILED",o.request=r,delete c[e],s.parentNode.removeChild(s),n(o)},s.href=u;var d=document.getElementsByTagName("head")[0];d.appendChild(s)}).then(function(){c[e]=0}));var r=u[e];if(0!==r)if(r)t.push(r[2]);else{var o=new Promise(function(t,n){r=u[e]=[t,n]});t.push(r[2]=o);var f,l=document.createElement("script");l.charset="utf-8",l.timeout=120,i.nc&&l.setAttribute("nonce",i.nc),l.src=a(e),f=function(t){l.onerror=l.onload=null,clearTimeout(h);var n=u[e];if(0!==n){if(n){var r=t&&("load"===t.type?"missing":t.type),c=t&&t.target&&t.target.src,o=new Error("Loading chunk "+e+" failed.\n("+r+": "+c+")");o.type=r,o.request=c,n[1](o)}u[e]=void 0}};var h=setTimeout(function(){f({type:"timeout",target:l})},12e4);l.onerror=l.onload=f,document.head.appendChild(l)}return Promise.all(t)},i.m=e,i.c=r,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)i.d(n,r,function(t){return e[t]}.bind(null,r));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i.oe=function(e){throw console.error(e),e};var f=window["webpackJsonp"]=window["webpackJsonp"]||[],l=f.push.bind(f);f.push=t,f=f.slice();for(var h=0;h<f.length;h++)t(f[h]);var s=l;n()})([]);</script><script src=static/js/chunk-elementUI.8ebdfbab.js></script><script src=static/js/chunk-libs.9cf9cc40.js></script><script src=static/js/app.3cc1fa6b.js></script></body></html>
|
@@ -0,0 +1 @@
|
||||
.gen-key{margin-bottom:0!important}fieldset{border:1px solid #ccc;color:grey;margin-left:40px;margin-bottom:20px}fieldset label{width:110px!important}fieldset .el-form-item__content{margin-left:110px!important}.key-view .el-form-item{margin-bottom:10px!important}
|
@@ -1 +0,0 @@
|
||||
.limit-tip[data-v-9b075514]{cursor:pointer;margin-left:10px}
|
@@ -0,0 +1 @@
|
||||
.custom-tree-node{-webkit-box-flex:1;-ms-flex:1;flex:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;font-size:14px;padding-right:8px}.el-input.is-disabled .el-input__inner,.el-radio__input.is-disabled+span.el-radio__label{color:#909399}.limit-tip[data-v-0ec28e9a]{cursor:pointer;margin-left:10px}
|
@@ -0,0 +1 @@
|
||||
.gen-key{margin-bottom:0!important}fieldset{border:1px solid #ccc;color:grey;margin-left:40px;margin-bottom:20px}fieldset label{width:110px!important}fieldset .el-form-item__content{margin-left:110px!important}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,21 @@
|
||||
package com.gitee.sop.adminserver;
|
||||
|
||||
import com.gitee.sop.adminserver.api.isv.result.IsvDetailDTO;
|
||||
import com.gitee.sop.adminserver.mapper.IsvInfoMapper;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public class IsvInfoMapperTest extends SopAdminServerApplicationTests {
|
||||
|
||||
@Autowired
|
||||
IsvInfoMapper isvInfoMapper;
|
||||
|
||||
@Test
|
||||
public void testGet() {
|
||||
IsvDetailDTO isvDetail = isvInfoMapper.getIsvDetail("2019032617262200001");
|
||||
System.out.println(isvDetail);
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package com.gitee.durcframework.easyopen.server;
|
||||
package com.gitee.sop.adminserver;
|
||||
|
||||
import org.junit.Test;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package com.gitee.durcframework.easyopen.server;
|
||||
package com.gitee.sop.adminserver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
@@ -1,4 +1,4 @@
|
||||
package com.gitee.durcframework.easyopen.server;
|
||||
package com.gitee.sop.adminserver;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@@ -92,12 +92,20 @@ export const constantRoutes = [
|
||||
path: '/isv',
|
||||
component: Layout,
|
||||
meta: { title: 'ISV管理', icon: 'user' },
|
||||
redirect: '/isv/list',
|
||||
children: [
|
||||
{
|
||||
path: 'list',
|
||||
name: 'IsvList',
|
||||
component: () => import('@/views/isv/index'),
|
||||
meta: { title: 'ISV列表' }
|
||||
},
|
||||
{
|
||||
path: 'keys',
|
||||
name: 'Keys',
|
||||
component: () => import('@/views/isv/keys'),
|
||||
hidden: true,
|
||||
meta: { title: '秘钥管理' }
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@@ -8,7 +8,7 @@ import { getToken, removeToken } from './auth'
|
||||
// 创建axios实例
|
||||
const client = axios.create({
|
||||
baseURL: process.env.VUE_APP_BASE_API, // api 的 base_url
|
||||
timeout: 10000 // 请求超时时间
|
||||
timeout: 60000 // 请求超时时间,60秒
|
||||
})
|
||||
|
||||
Object.assign(Vue.prototype, {
|
||||
|
@@ -25,32 +25,13 @@
|
||||
label="appKey"
|
||||
width="250"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="secret"
|
||||
label="secret"
|
||||
width="80"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button v-if="scope.row.signType === 2" type="text" size="mini" @click="onShowSecret(scope.row)">查看</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop=""
|
||||
label="公私钥"
|
||||
label="秘钥"
|
||||
width="80"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button v-if="scope.row.signType === 1" type="text" size="mini" @click="onShowPriPubKey(scope.row)">查看</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="signType"
|
||||
label="签名类型"
|
||||
width="80"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.signType === 1">RSA2</span>
|
||||
<span v-if="scope.row.signType === 2">MD5</span>
|
||||
<el-button type="text" size="mini" @click="onShowKeys(scope.row)">查看</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
@@ -83,11 +64,11 @@
|
||||
/>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
fixed="right"
|
||||
width="100"
|
||||
width="150"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="onTableUpdate(scope.row)">修改</el-button>
|
||||
<el-button type="text" size="mini" @click="onKeysUpdate(scope.row)">秘钥管理</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -116,26 +97,9 @@
|
||||
label-width="120px"
|
||||
size="mini"
|
||||
>
|
||||
<el-form-item label="">
|
||||
<el-button size="mini" @click="onDataGen">一键生成数据</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item prop="appKey" label="appKey">
|
||||
<el-input v-model="isvDialogFormData.appKey" size="mini" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="signType" label="签名方式">
|
||||
<el-radio-group v-model="isvDialogFormData.signType">
|
||||
<el-radio :label="1" name="status">RSA2</el-radio>
|
||||
<el-radio :label="2" name="status">MD5</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-show="isvDialogFormData.signType === 2" prop="secret" label="secret">
|
||||
<el-input v-model="isvDialogFormData.secret" size="mini" />
|
||||
</el-form-item>
|
||||
<el-form-item v-show="isvDialogFormData.signType === 1" prop="pubKey" label="公钥">
|
||||
<el-input v-model="isvDialogFormData.pubKey" type="textarea" />
|
||||
</el-form-item>
|
||||
<el-form-item v-show="isvDialogFormData.signType === 1" prop="priKey" label="私钥">
|
||||
<el-input v-model="isvDialogFormData.priKey" type="textarea" />
|
||||
<el-form-item label="appKey">
|
||||
<span v-if="isvDialogFormData.id === 0" style="color: gray;">(系统自动生成)</span>
|
||||
<span v-else>{{ isvDialogFormData.appKey }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="角色">
|
||||
<el-checkbox-group v-model="isvDialogFormData.roleCode">
|
||||
@@ -154,31 +118,75 @@
|
||||
<el-button type="primary" @click="onIsvDialogSave">保 存</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!--view keys dialog-->
|
||||
<el-dialog
|
||||
title="秘钥信息"
|
||||
:visible.sync="isvKeysDialogVisible"
|
||||
@close="resetForm('isvKeysFrom')"
|
||||
>
|
||||
<el-form
|
||||
ref="isvKeysFrom"
|
||||
:model="isvKeysFormData"
|
||||
label-width="160px"
|
||||
size="mini"
|
||||
class="key-view"
|
||||
>
|
||||
<el-form-item label="">
|
||||
<el-alert
|
||||
title="带 ★ 的分配给开发者"
|
||||
type="warning"
|
||||
:closable="false"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="selfLabel('appKey')">
|
||||
<span>{{ isvKeysFormData.appKey }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="签名方式">
|
||||
<span v-if="isvKeysFormData.signType === 1">RSA2</span>
|
||||
<span v-if="isvKeysFormData.signType === 2">MD5</span>
|
||||
</el-form-item>
|
||||
<el-form-item v-show="showKeys()" label="秘钥格式">
|
||||
<span v-if="isvKeysFormData.keyFormat === 1">PKCS8(JAVA适用)</span>
|
||||
<span v-if="isvKeysFormData.keyFormat === 2">PKCS1(非JAVA适用)</span>
|
||||
</el-form-item>
|
||||
<el-form-item v-show="isvKeysFormData.signType === 2" :label="selfLabel('secret')">
|
||||
<span>{{ isvKeysFormData.secret }}</span>
|
||||
</el-form-item>
|
||||
<fieldset v-show="showKeys()">
|
||||
<legend>ISV公私钥</legend>
|
||||
<el-form-item label="ISV公钥">
|
||||
<el-input v-model="isvKeysFormData.publicKeyIsv" type="textarea" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item :label="selfLabel('ISV私钥')">
|
||||
<el-input v-model="isvKeysFormData.privateKeyIsv" type="textarea" readonly />
|
||||
</el-form-item>
|
||||
</fieldset>
|
||||
<fieldset v-show="showKeys()">
|
||||
<legend>平台公私钥</legend>
|
||||
<el-form-item :label="selfLabel('平台公钥')">
|
||||
<el-input v-model="isvKeysFormData.publicKeyPlatform" type="textarea" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item prop="privateKeyPlatform" label="平台私钥">
|
||||
<el-input v-model="isvKeysFormData.privateKeyPlatform" type="textarea" readonly />
|
||||
</el-form-item>
|
||||
</fieldset>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="isvKeysDialogVisible = false">关 闭</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.gen-key {margin-bottom: 0px !important;}
|
||||
fieldset {border: 1px solid #ccc; color: gray;margin-left: 40px;margin-bottom: 20px;}
|
||||
fieldset label {width: 110px !important;}
|
||||
fieldset .el-form-item__content {margin-left: 110px !important;}
|
||||
.key-view .el-form-item {margin-bottom: 10px !important;}
|
||||
</style>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
const validateSecret = (rule, value, callback) => {
|
||||
if (this.isvDialogFormData.signType === 2) {
|
||||
if (value === '') {
|
||||
callback(new Error('不能为空'))
|
||||
}
|
||||
if (value.length > 200) {
|
||||
callback(new Error('长度不能超过200'))
|
||||
}
|
||||
}
|
||||
callback()
|
||||
}
|
||||
const validatePubPriKey = (rule, value, callback) => {
|
||||
if (this.isvDialogFormData.signType === 1) {
|
||||
if (value === '') {
|
||||
callback(new Error('不能为空'))
|
||||
}
|
||||
}
|
||||
callback()
|
||||
}
|
||||
return {
|
||||
searchFormData: {
|
||||
appKey: '',
|
||||
@@ -195,11 +203,6 @@ export default {
|
||||
isvDialogTitle: '新增ISV',
|
||||
isvDialogFormData: {
|
||||
id: 0,
|
||||
appKey: '',
|
||||
secret: '',
|
||||
pubKey: '',
|
||||
priKey: '',
|
||||
signType: 1,
|
||||
status: 1,
|
||||
roleCode: []
|
||||
},
|
||||
@@ -207,16 +210,17 @@ export default {
|
||||
appKey: [
|
||||
{ required: true, message: '不能为空', trigger: 'blur' },
|
||||
{ min: 1, max: 100, message: '长度在 1 到 100 个字符', trigger: 'blur' }
|
||||
],
|
||||
secret: [
|
||||
{ validator: validateSecret, trigger: 'blur' }
|
||||
],
|
||||
pubKey: [
|
||||
{ validator: validatePubPriKey, trigger: 'blur' }
|
||||
],
|
||||
priKey: [
|
||||
{ validator: validatePubPriKey, trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
isvKeysDialogVisible: false,
|
||||
isvKeysFormData: {
|
||||
appKey: '',
|
||||
secret: '',
|
||||
publicKeyIsv: '',
|
||||
privateKeyIsv: '',
|
||||
publicKeyPlatform: '',
|
||||
privateKeyPlatform: '',
|
||||
signType: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -237,16 +241,12 @@ export default {
|
||||
})
|
||||
}
|
||||
},
|
||||
onShowSecret: function(row) {
|
||||
this.$alert(row.secret, 'secret')
|
||||
},
|
||||
onShowPriPubKey: function(row) {
|
||||
const pubKey = row.pubKey
|
||||
const priKey = row.priKey
|
||||
const content = '<div>公钥:<textarea style="width: 380px;height: 100px;" readonly="readonly">' + pubKey + '</textarea><br>' +
|
||||
'私钥:<textarea style="width: 380px;height: 100px;" readonly="readonly">' + priKey + '</textarea></div>'
|
||||
this.$alert(content, '公私钥', {
|
||||
dangerouslyUseHTMLString: true
|
||||
onShowKeys: function(row) {
|
||||
this.post('isv.keys.get', { appKey: row.appKey }, function(resp) {
|
||||
this.isvKeysDialogVisible = true
|
||||
this.$nextTick(() => {
|
||||
Object.assign(this.isvKeysFormData, resp.data)
|
||||
})
|
||||
})
|
||||
},
|
||||
onSearchTable: function() {
|
||||
@@ -268,6 +268,9 @@ export default {
|
||||
})
|
||||
})
|
||||
},
|
||||
onKeysUpdate: function(row) {
|
||||
this.$router.push({ path: `keys?appKey=${row.appKey}` })
|
||||
},
|
||||
onSizeChange: function(size) {
|
||||
this.searchFormData.pageSize = size
|
||||
this.loadTable()
|
||||
@@ -277,9 +280,11 @@ export default {
|
||||
this.loadTable()
|
||||
},
|
||||
onAdd: function() {
|
||||
this.isvDialogFormData.id = 0
|
||||
this.isvDialogTitle = '新增ISV'
|
||||
this.isvDialogVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.isvDialogFormData.id = 0
|
||||
})
|
||||
},
|
||||
onIsvDialogSave: function() {
|
||||
const that = this
|
||||
@@ -294,8 +299,12 @@ export default {
|
||||
})
|
||||
},
|
||||
onIsvDialogClose: function() {
|
||||
this.$refs.isvForm.resetFields()
|
||||
this.isvDialogVisible = false
|
||||
this.resetForm('isvForm')
|
||||
this.isvDialogFormData.status = 1
|
||||
this.isvDialogFormData.roleCode = []
|
||||
},
|
||||
selfLabel: function(lab) {
|
||||
return '★ ' + lab
|
||||
},
|
||||
roleRender: function(row) {
|
||||
const html = []
|
||||
@@ -305,27 +314,8 @@ export default {
|
||||
}
|
||||
return html.join(', ')
|
||||
},
|
||||
onDataGen: function() {
|
||||
this.post('isv.form.gen', {}, function(resp) {
|
||||
const data = resp.data
|
||||
// 如果是新增状态
|
||||
if (this.isvDialogFormData.id === 0) {
|
||||
Object.assign(this.isvDialogFormData, data)
|
||||
} else {
|
||||
const signType = this.isvDialogFormData.signType
|
||||
// RSA2
|
||||
if (signType === 1) {
|
||||
Object.assign(this.isvDialogFormData, {
|
||||
pubKey: data.pubKey,
|
||||
priKey: data.priKey
|
||||
})
|
||||
} else if (signType === 2) {
|
||||
Object.assign(this.isvDialogFormData, {
|
||||
secret: data.secret
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
showKeys: function() {
|
||||
return this.isvKeysFormData.signType === 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
172
sop-admin/sop-admin-vue/src/views/isv/keys.vue
Normal file
172
sop-admin/sop-admin-vue/src/views/isv/keys.vue
Normal file
@@ -0,0 +1,172 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-button class="el-icon-back" type="text" @click="onBack">返回</el-button>
|
||||
<el-form
|
||||
ref="isvKeysForm"
|
||||
:rules="rulesIsvKeysForm"
|
||||
:model="isvKeysFormData"
|
||||
label-width="160px"
|
||||
size="mini"
|
||||
style="width: 700px;"
|
||||
>
|
||||
<el-form-item label="">
|
||||
<el-alert
|
||||
title="带 ★ 的分配给开发者"
|
||||
type="warning"
|
||||
:closable="false"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="selfLabel('appKey')">
|
||||
<div>{{ isvKeysFormData.appKey }}</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="签名方式">
|
||||
<el-radio-group v-model="isvKeysFormData.signType">
|
||||
<el-radio :label="1" name="status">RSA2</el-radio>
|
||||
<el-radio :label="2" name="status">MD5</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-show="showKeys()" label="秘钥格式">
|
||||
<el-radio-group v-model="isvKeysFormData.keyFormat">
|
||||
<el-radio :label="1" name="keyFormat">PKCS8(JAVA适用)</el-radio>
|
||||
<el-radio :label="2" name="keyFormat">PKCS1(非JAVA适用)</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-show="isvKeysFormData.signType === 2" prop="secret" :label="selfLabel('secret')">
|
||||
<el-input v-model="isvKeysFormData.secret" /> <el-button type="text" @click="onGenSecret">重新生成</el-button>
|
||||
</el-form-item>
|
||||
<fieldset v-show="showKeys()">
|
||||
<legend>ISV公私钥</legend>
|
||||
<el-form-item class="gen-key">
|
||||
<el-button type="text" @click="onGenKeysIsv">重新生成</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item prop="publicKeyIsv" label="ISV公钥">
|
||||
<el-input v-model="isvKeysFormData.publicKeyIsv" type="textarea" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="privateKeyIsv" :label="selfLabel('ISV私钥')">
|
||||
<el-input v-model="isvKeysFormData.privateKeyIsv" type="textarea" />
|
||||
</el-form-item>
|
||||
</fieldset>
|
||||
<fieldset v-show="showKeys()">
|
||||
<legend>平台公私钥</legend>
|
||||
<el-form-item class="gen-key">
|
||||
<el-button type="text" @click="onGenKeysPlatform">重新生成</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item prop="publicKeyPlatform" :label="selfLabel('平台公钥')">
|
||||
<el-input v-model="isvKeysFormData.publicKeyPlatform" type="textarea" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="privateKeyPlatform" label="平台私钥">
|
||||
<el-input v-model="isvKeysFormData.privateKeyPlatform" type="textarea" />
|
||||
</el-form-item>
|
||||
</fieldset>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
||||
<el-button @click="onBack">取消</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
<style>
|
||||
.gen-key {margin-bottom: 0px !important;}
|
||||
fieldset {border: 1px solid #ccc; color: gray;margin-left: 40px;margin-bottom: 20px;}
|
||||
fieldset label {width: 110px !important;}
|
||||
fieldset .el-form-item__content {margin-left: 110px !important;}
|
||||
</style>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
const validateSecret = (rule, value, callback) => {
|
||||
if (this.isvKeysFormData.signType === 2) {
|
||||
if (value === '') {
|
||||
callback(new Error('不能为空'))
|
||||
}
|
||||
if (value.length > 200) {
|
||||
callback(new Error('长度不能超过200'))
|
||||
}
|
||||
}
|
||||
callback()
|
||||
}
|
||||
const validatePubPriKey = (rule, value, callback) => {
|
||||
if (this.isvKeysFormData.signType === 1) {
|
||||
if (value === '') {
|
||||
callback(new Error('不能为空'))
|
||||
}
|
||||
}
|
||||
callback()
|
||||
}
|
||||
return {
|
||||
isvKeysFormData: {
|
||||
appKey: '',
|
||||
secret: '',
|
||||
keyFormat: 1,
|
||||
publicKeyIsv: '',
|
||||
privateKeyIsv: '',
|
||||
publicKeyPlatform: '',
|
||||
privateKeyPlatform: '',
|
||||
signType: 1
|
||||
},
|
||||
rulesIsvKeysForm: {
|
||||
secret: [
|
||||
{ validator: validateSecret, trigger: 'blur' }
|
||||
],
|
||||
publicKeyIsv: [
|
||||
{ validator: validatePubPriKey, trigger: 'blur' }
|
||||
],
|
||||
privateKeyIsv: [
|
||||
{ validator: validatePubPriKey, trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
const query = this.$route.query
|
||||
this.isvKeysFormData.appKey = query.appKey
|
||||
this.loadForm()
|
||||
},
|
||||
methods: {
|
||||
loadForm: function() {
|
||||
this.post('isv.keys.get', { appKey: this.isvKeysFormData.appKey }, function(resp) {
|
||||
Object.assign(this.isvKeysFormData, resp.data)
|
||||
})
|
||||
},
|
||||
selfLabel: function(lab) {
|
||||
return '★ ' + lab
|
||||
},
|
||||
onSubmit: function() {
|
||||
this.$refs.isvKeysForm.validate((valid) => {
|
||||
if (valid) {
|
||||
this.post('isv.keys.update', this.isvKeysFormData, function() {
|
||||
this.tip('保存成功')
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
onBack: function() {
|
||||
this.$router.push({ path: 'list' })
|
||||
},
|
||||
onGenKeysPlatform: function() {
|
||||
this.post('isv.keys.gen', {}, function(resp) {
|
||||
this.tip('生成公私钥成功')
|
||||
const data = resp.data
|
||||
this.isvKeysFormData.publicKeyPlatform = data.publicKey
|
||||
this.isvKeysFormData.privateKeyPlatform = data.privateKey
|
||||
})
|
||||
},
|
||||
onGenKeysIsv: function() {
|
||||
this.post('isv.keys.gen', { keyFormat: this.isvKeysFormData.keyFormat }, function(resp) {
|
||||
this.tip('生成公私钥成功')
|
||||
const data = resp.data
|
||||
this.isvKeysFormData.publicKeyIsv = data.publicKey
|
||||
this.isvKeysFormData.privateKeyIsv = data.privateKey
|
||||
})
|
||||
},
|
||||
onGenSecret: function() {
|
||||
this.post('isv.secret.gen', {}, function(resp) {
|
||||
this.isvKeysFormData.secret = resp.data
|
||||
})
|
||||
},
|
||||
showKeys: function() {
|
||||
return this.isvKeysFormData.signType === 1
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@@ -231,7 +231,18 @@
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.custom-tree-node {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 14px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
.el-input.is-disabled .el-input__inner {color: #909399;}
|
||||
.el-radio__input.is-disabled+span.el-radio__label {color: #909399;}
|
||||
</style>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
@@ -425,6 +436,7 @@ export default {
|
||||
},
|
||||
onLimitDialogClose: function() {
|
||||
this.resetForm('limitDialogForm')
|
||||
this.limitDialogFormData.limitStatus = 0
|
||||
},
|
||||
infoRender: function(row) {
|
||||
const html = []
|
||||
|
Reference in New Issue
Block a user