优化 非对称加密 50%(未完)

v1.4.1
hiparker 4 years ago
parent 2db84d57e6
commit a8177cf1dd

@ -19,13 +19,13 @@ package org.opsli.common.annotation;
import java.lang.annotation.*;
/**
*
* Api
* @author Parker
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InterfaceCrypto {
public @interface ApiCryptoAsymmetric {
/** 加密启用状态 */
boolean enable() default true;

@ -34,6 +34,13 @@
<version>${api.version}</version>
</dependency>
<!-- 引入加解密插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>
<artifactId>opsli-plugins-crypto</artifactId>
<version>${plugins.version}</version>
</dependency>
<!-- 引入Redis插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>

@ -20,6 +20,10 @@ import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.TypeUtil;
import lombok.extern.slf4j.Slf4j;
import opsli.plugins.crypto.CryptoPlugin;
import opsli.plugins.crypto.enums.CryptoAsymmetricType;
import opsli.plugins.crypto.model.CryptoAsymmetric;
import opsli.plugins.crypto.strategy.CryptoAsymmetricService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@ -27,10 +31,13 @@ import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.opsli.api.base.encrypt.BaseEncrypt;
import org.opsli.api.base.result.ResultVo;
import org.opsli.common.annotation.InterfaceCrypto;
import org.opsli.api.wrapper.system.options.OptionsModel;
import org.opsli.common.annotation.ApiCryptoAsymmetric;
import org.opsli.common.enums.OptionsType;
import org.opsli.common.exception.ServiceException;
import org.opsli.core.msg.CoreMsg;
import org.opsli.core.utils.CryptoAsymmetricUtil;
import org.opsli.core.utils.OptionsUtil;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@ -42,7 +49,7 @@ import java.util.Map;
import static org.opsli.common.constants.OrderConstants.ENCRYPT_ADN_DECRYPT_AOP_SORT;
/**
*
* Api
*
* @author parker
* @date 2021-01-23
@ -51,9 +58,9 @@ import static org.opsli.common.constants.OrderConstants.ENCRYPT_ADN_DECRYPT_AOP_
@Order(ENCRYPT_ADN_DECRYPT_AOP_SORT)
@Aspect
@Component
public class InterfaceCryptoAop {
public class ApiCryptoAsymmetricAop {
@Pointcut("@annotation(org.opsli.common.annotation.InterfaceCrypto)")
@Pointcut("@annotation(org.opsli.common.annotation.ApiCryptoAsymmetric)")
public void encryptAndDecrypt() {
}
@ -73,9 +80,42 @@ public class InterfaceCryptoAop {
// 获得 方法
Method method = signature.getMethod();
// 获得方法注解
InterfaceCrypto annotation =
method.getAnnotation(InterfaceCrypto.class);
ApiCryptoAsymmetric annotation =
method.getAnnotation(ApiCryptoAsymmetric.class);
if(annotation != null){
// TODO 后期引入 享元池设计 防止过度创建对象 先保障能跑起来 2021年5月17日18:23:56 以下全是要优化的地方
// 获得非对称加解密 执行器
CryptoAsymmetricService asymmetric = CryptoPlugin.getAsymmetric();
// 加解密模型
CryptoAsymmetric cryptoModel = asymmetric.createNilModel();
// 获得缓存配置
// 加解密方式
OptionsModel cryptoAsymmetric = OptionsUtil.getOptionByCode(OptionsType.CRYPTO_ASYMMETRIC);
// 公钥
OptionsModel cryptoAsymmetricPublicKey =
OptionsUtil.getOptionByCode(OptionsType.CRYPTO_ASYMMETRIC_PUBLIC_KEY);
// 私钥
OptionsModel cryptoAsymmetricPrivateKey =
OptionsUtil.getOptionByCode(OptionsType.CRYPTO_ASYMMETRIC_PRIVATE_KEY);
// 非法验证
if(cryptoAsymmetric == null || cryptoAsymmetricPublicKey == null ||
cryptoAsymmetricPrivateKey == null
){
throw new RuntimeException();
}
// 加解密方式枚举
CryptoAsymmetricType cryptoType = CryptoAsymmetricType.getCryptoType(
cryptoAsymmetric.getOptionValue());
// 非法验证
if(cryptoType == null){
throw new RuntimeException();
}
// TODO 都需要优化掉
cryptoModel.setCryptoType(cryptoType);
cryptoModel.setPublicKey(cryptoAsymmetricPublicKey.getOptionValue());
cryptoModel.setPrivateKey(cryptoAsymmetricPrivateKey.getOptionValue());
// 1. 拆解请求数据
// request 解密
@ -88,7 +128,7 @@ public class InterfaceCryptoAop {
BaseEncrypt baseEncrypt = (BaseEncrypt) arg;
String encryptData = baseEncrypt.getEncryptData();
// 解密对象
Object dataToObj = CryptoAsymmetricUtil.decryptToObj(encryptData);
Object dataToObj = asymmetric.decryptToObj(cryptoModel, encryptData);
// 根据方法类型转化对象
Type type = TypeUtil.getParamType(method, i);
@ -124,11 +164,12 @@ public class InterfaceCryptoAop {
if(returnValue instanceof ResultVo){
ResultVo<Object> ret = (ResultVo<Object>) returnValue;
ret.setData(
CryptoAsymmetricUtil.encrypt(ret.getData())
asymmetric.encrypt(cryptoModel, ret.getData())
);
returnValue = ret;
}else {
returnValue = CryptoAsymmetricUtil.encrypt(returnValue);
returnValue = asymmetric.encrypt(cryptoModel, returnValue);
CryptoAsymmetricUtil.encrypt(returnValue);
}
}catch (Exception e){
// 非对称加密失败

@ -242,7 +242,6 @@ public final class CryptoAsymmetricUtil {
@Data
public static class CryptoAsymmetric {
/** 加解密类别 */
private String cryptoType;

@ -44,7 +44,7 @@ public final class ValidationUtil {
/**
*
* @param obj
* @param obj
*/
public static void verify(Object obj){
if(obj == null){
@ -81,9 +81,9 @@ public final class ValidationUtil {
/**
*
* @param field
* @param types
* @param fieldValue
* @param field
* @param types
* @param fieldValue
*/
private static void check(Field field, ValiArgsType[] types, Object fieldValue){
// 获得字段名
@ -326,9 +326,9 @@ public final class ValidationUtil {
/**
*
* @param field
* @param maxLength
* @param fieldValue
* @param field
* @param maxLength
* @param fieldValue
*/
private static void checkMax(Field field, int maxLength, Object fieldValue){
// 获得字段名
@ -359,9 +359,9 @@ public final class ValidationUtil {
/**
*
* @param field
* @param minLength
* @param fieldValue
* @param field
* @param minLength
* @param fieldValue
*/
private static void checkMin(Field field, int minLength, Object fieldValue){
// 获得字段名

@ -24,9 +24,10 @@ import org.opsli.api.base.result.ResultVo;
import org.opsli.api.wrapper.system.options.OptionsModel;
import org.opsli.api.wrapper.system.tenant.TenantModel;
import org.opsli.api.wrapper.system.user.UserModel;
import org.opsli.common.annotation.InterfaceCrypto;
import org.opsli.common.annotation.ApiCryptoAsymmetric;
import org.opsli.common.annotation.Limiter;
import org.opsli.common.enums.DictType;
import org.opsli.core.utils.ValidationUtil;
import org.opsli.core.api.TokenThreadLocal;
import org.opsli.common.enums.AlertType;
import org.opsli.common.enums.OptionsType;
@ -34,7 +35,6 @@ import org.opsli.common.exception.TokenException;
import org.opsli.common.thread.refuse.AsyncProcessQueueReFuse;
import org.opsli.common.utils.IPUtil;
import org.opsli.core.msg.TokenMsg;
import org.opsli.core.security.shiro.realm.JwtRealm;
import org.opsli.core.utils.*;
import org.opsli.modulars.system.login.entity.LoginForm;
import org.opsli.modulars.system.user.service.IUserService;
@ -71,7 +71,7 @@ public class LoginRestController {
*
*/
@Limiter
@InterfaceCrypto(responseEncrypt = false)
@ApiCryptoAsymmetric(responseEncrypt = false)
@ApiOperation(value = "登录", notes = "登录")
@PostMapping("/system/login")
public ResultVo<UserTokenUtil.TokenRet> login(@RequestBody LoginForm form, HttpServletRequest request){

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>opsli-plugins</artifactId>
<groupId>org.opsliframework.boot</groupId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>opsli-plugins-crypto</artifactId>
<version>${project.parent.version}</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>

@ -0,0 +1,47 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package opsli.plugins.crypto;
import lombok.extern.slf4j.Slf4j;
import opsli.plugins.crypto.strategy.CryptoAsymmetricService;
import opsli.plugins.crypto.strategy.impl.CryptoAsymmetricAsymmetricImpl;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.common.utils
* @Author: Parker
* @CreateTime: 2020-09-22 17:29
* @Description:
*/
@Slf4j
public class CryptoPlugin {
/** 非对称加密 */
private static final CryptoAsymmetricService CRYPTO_ASYMMETRIC = new CryptoAsymmetricAsymmetricImpl();
/**
*
* @return CryptoAsymmetricService
*/
public static CryptoAsymmetricService getAsymmetric(){
return CRYPTO_ASYMMETRIC;
}
// ================
private CryptoPlugin(){}
}

@ -0,0 +1,61 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package opsli.plugins.crypto.enums;
/**
*
*
* @author Parker
* @date 202151716:48:14
*/
public enum CryptoAsymmetricType {
/** 非对称算法类型 */
RSA("RSA", "RSA 算法"),
SM2("SM2", "SM2 算法"),
ECIES("ECIES", "ECIES 算法"),
;
private final String code;
private final String desc;
public static CryptoAsymmetricType getCryptoType(String code) {
CryptoAsymmetricType[] types = values();
for (CryptoAsymmetricType type : types) {
if (type.code.equalsIgnoreCase(code)) {
return type;
}
}
return null;
}
public String getCode() {
return this.code;
}
public String getDesc() {
return this.desc;
}
// =================
CryptoAsymmetricType(final String code, final String desc) {
this.code = code;
this.desc = desc;
}
}

@ -0,0 +1,36 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package opsli.plugins.crypto.exception;
import org.opsli.common.base.msg.BaseMsg;
import org.opsli.common.exception.ServiceException;
/**
*
*
* @author Parker
* @date 202151716:49:53
*/
public class CryptoException extends ServiceException {
public CryptoException(Integer code, String errorMessage) {
super(code, errorMessage);
}
public CryptoException(BaseMsg msg) {
super(msg);
}
}

@ -0,0 +1,38 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package opsli.plugins.crypto.model;
import lombok.Data;
import opsli.plugins.crypto.enums.CryptoAsymmetricType;
/**
*
*
* @author Parker
* @date 202151715:59:52
*/
@Data
public class CryptoAsymmetric {
/** 加解密类别 */
private CryptoAsymmetricType cryptoType;
/** 公钥 */
private String publicKey;
/** 私钥 */
private String privateKey;
}

@ -0,0 +1,55 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package opsli.plugins.crypto.msg;
import org.opsli.common.base.msg.BaseMsg;
/**
* -
*
* @author Parker
* @date 202151716:46:42
*/
public enum CryptoMsg implements BaseMsg {
/** 加解密 */
CRYPTO_EXCEPTION_EN(10702,"加密失败"),
CRYPTO_EXCEPTION_DE(10703,"解密失败"),
CRYPTO_EXCEPTION_REFLEX(10704,"解密反射失败"),
CRYPTO_EXCEPTION_MODEL_NULL(10705,"配置信息未初始化"),
CRYPTO_EXCEPTION_TO_JSON(10706,"加密数据转换Json失败"),
CRYPTO_EXCEPTION_HANDLER_NULL(10707,"无法获得加解密执行器"),
;
private final int code;
private final String message;
CryptoMsg(int code, String message){
this.code = code;
this.message = message;
}
@Override
public Integer getCode() {
return this.code;
}
@Override
public String getMessage() {
return this.message;
}
}

@ -0,0 +1,67 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package opsli.plugins.crypto.strategy;
import opsli.plugins.crypto.enums.CryptoAsymmetricType;
import opsli.plugins.crypto.model.CryptoAsymmetric;
/**
*
*
* @author Parker
* @date 202151715:49:15
*/
public interface CryptoAsymmetricService {
/**
*
* @return Model
*/
CryptoAsymmetric createNilModel();
/**
*
* @param cryptoAsymmetricType
* @return Model
*/
CryptoAsymmetric createKeyModel(final CryptoAsymmetricType cryptoAsymmetricType);
/**
*
* @param model
* @param data
* @return String
*/
String encrypt(final CryptoAsymmetric model, final Object data);
/**
*
* @param model
* @param data
* @return Object
*/
Object decryptToObj(final CryptoAsymmetric model, final String data);
/**
*
* @param model
* @param data
* @return String
*/
String decrypt(final CryptoAsymmetric model, final String data);
}

@ -0,0 +1,225 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package opsli.plugins.crypto.strategy.impl;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.*;
import cn.hutool.json.JSONException;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import opsli.plugins.crypto.enums.CryptoAsymmetricType;
import opsli.plugins.crypto.exception.CryptoException;
import opsli.plugins.crypto.model.CryptoAsymmetric;
import opsli.plugins.crypto.msg.CryptoMsg;
import opsli.plugins.crypto.strategy.CryptoAsymmetricService;
import org.apache.commons.lang3.StringUtils;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.utils
* @Author: Parker
* @CreateTime: 2020-09-19 20:03
* @Description:
*/
@Slf4j
public class CryptoAsymmetricAsymmetricImpl implements CryptoAsymmetricService {
/**
*
* @return Model
*/
@Override
public CryptoAsymmetric createNilModel() {
return new CryptoAsymmetric();
}
/**
*
* @param cryptoAsymmetricType
* @return Model
*/
@Override
public CryptoAsymmetric createKeyModel(final CryptoAsymmetricType cryptoAsymmetricType){
CryptoAsymmetric model = this.createNilModel();
model.setCryptoType(cryptoAsymmetricType);
switch (cryptoAsymmetricType){
case RSA:
RSA rsa = SecureUtil.rsa();
model.setPublicKey(rsa.getPublicKeyBase64());
model.setPrivateKey(rsa.getPrivateKeyBase64());
break;
case SM2:
SM2 sm2 = SmUtil.sm2();
model.setPublicKey(sm2.getPublicKeyBase64());
model.setPrivateKey(sm2.getPrivateKeyBase64());
break;
case ECIES:
ECIES ecies = new ECIES();
model.setPublicKey(ecies.getPublicKeyBase64());
model.setPrivateKey(ecies.getPrivateKeyBase64());
break;
default:
break;
}
return model;
}
/**
*
* @param model
* @param data
* @return String
*/
@Override
public String encrypt(final CryptoAsymmetric model, final Object data){
// 非法验证
if(model == null ||
model.getCryptoType() == null ||
StringUtils.isEmpty(model.getPrivateKey()) ||
StringUtils.isEmpty(model.getPublicKey())
){
// 配置信息未初始化
throw new CryptoException(CryptoMsg.CRYPTO_EXCEPTION_MODEL_NULL);
}
// 原始/加密 数据
String encryptedStr;
try {
encryptedStr = JSONUtil.toJsonStr(data);
// 创建执行器
AbstractAsymmetricCrypto<?> cryptoHandler = this.createCryptoHandler(model);
if(cryptoHandler == null){
// 无法获得加解密执行器
throw new CryptoException(CryptoMsg.CRYPTO_EXCEPTION_HANDLER_NULL);
}
// 执行加密操作
encryptedStr = cryptoHandler.encryptBase64(
StrUtil.bytes(encryptedStr, CharsetUtil.CHARSET_UTF_8), KeyType.PublicKey);
}catch (JSONException jse){
// 加密数据转换Json失败
throw new CryptoException(CryptoMsg.CRYPTO_EXCEPTION_TO_JSON);
}catch (CryptoException ce){
// 如果检测到已有异常 则直接抛出
throw ce;
}catch (Exception e){
// 加密失败
throw new CryptoException(CryptoMsg.CRYPTO_EXCEPTION_EN);
}
return encryptedStr;
}
/**
* - Obj
* @param model
* @param data
* @return Object
*/
@Override
public Object decryptToObj(final CryptoAsymmetric model, final String data){
Object obj;
String decryptedData = decrypt(model, data);
try{
obj = JSONUtil.parse(decryptedData);
}catch (Exception e){
// 非对称解密反射失败
throw new CryptoException(CryptoMsg.CRYPTO_EXCEPTION_REFLEX);
}
return obj;
}
/**
*
* @param model
* @param data
* @return String
*/
@Override
public String decrypt(final CryptoAsymmetric model, final String data){
// 非法验证
if(model == null ||
model.getCryptoType() == null ||
StringUtils.isEmpty(model.getPrivateKey()) ||
StringUtils.isEmpty(model.getPublicKey())
){
// 配置信息未初始化
throw new CryptoException(CryptoMsg.CRYPTO_EXCEPTION_MODEL_NULL);
}
// 如果解密内容为空 则返回原内容
if(StringUtils.isEmpty(data)){
return data;
}
String decryptStr;
try {
// 创建执行器
AbstractAsymmetricCrypto<?> cryptoHandler = this.createCryptoHandler(model);
if(cryptoHandler == null){
// 无法获得加解密执行器
throw new CryptoException(CryptoMsg.CRYPTO_EXCEPTION_HANDLER_NULL);
}
// 处理数据
String currData = data.replaceAll(" ", "+");
// 解密数据 - 返回Json 格式String
decryptStr = cryptoHandler.decryptStr(currData, KeyType.PrivateKey);
}catch (CryptoException ce){
// 如果检测到已有异常 则直接抛出
throw ce;
}catch (Exception e){
// 解密失败
throw new CryptoException(CryptoMsg.CRYPTO_EXCEPTION_DE);
}
return decryptStr;
}
/**
*
* @param model
* @return
*/
private AbstractAsymmetricCrypto<?> createCryptoHandler(final CryptoAsymmetric model){
AbstractAsymmetricCrypto<?> encryptor = null;
switch (model.getCryptoType()){
// 注意 这里 switch 使用的是代码块 方法执行完毕后 直接回收对象
case RSA:{
encryptor = SecureUtil.rsa(model.getPrivateKey(), model.getPublicKey());
break;
}
case SM2:{
encryptor = SmUtil.sm2(model.getPrivateKey(), model.getPublicKey());
break;
}
case ECIES:{
encryptor = new ECIES(model.getPrivateKey(), model.getPublicKey());
break;
}
default:
break;
}
return encryptor;
}
}

@ -21,6 +21,7 @@
<module>opsli-plugins-excel</module>
<module>opsli-plugins-redisson</module>
<module>opsli-plugins-waf</module>
<module>opsli-plugins-crypto</module>
</modules>
<dependencyManagement>

Loading…
Cancel
Save