REM:
1. 增加协议安全加密、解密服务
2. 重构接口协议加密、解密方法
This commit is contained in:
HuangXin 2020-09-08 18:04:27 +08:00
parent f3d70092fb
commit d19248c1ce
6 changed files with 245 additions and 177 deletions

View File

@ -1,7 +1,7 @@
package com.dispose.interceptor; package com.dispose.interceptor;
import com.dispose.service.ProtocolSecurityService;
import com.security.annotation.Decryption; import com.security.annotation.Decryption;
import com.security.protocol.DecryptRequestProtocol;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
@ -10,16 +10,25 @@ import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice; import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;
import javax.annotation.Resource;
import java.io.IOException;
import java.lang.reflect.Type; import java.lang.reflect.Type;
/** /**
* The type Protocol security. * The type Request protocol security.
* *
* @author <huangxin@cmhi.chinamoblie.com> * @author <huangxin@cmhi.chinamoblie.com>
*/ */
@Slf4j @Slf4j
@RestControllerAdvice @RestControllerAdvice
public class RequestProtocolSecurity implements RequestBodyAdvice { public class RequestProtocolSecurity implements RequestBodyAdvice {
/**
* The Protocol security service.
*/
@Resource
private ProtocolSecurityService protocolSecurityService;
/** /**
* Supports boolean. * Supports boolean.
* *
@ -50,8 +59,8 @@ public class RequestProtocolSecurity implements RequestBodyAdvice {
public HttpInputMessage beforeBodyRead(@NotNull HttpInputMessage httpInputMessage, public HttpInputMessage beforeBodyRead(@NotNull HttpInputMessage httpInputMessage,
@NotNull MethodParameter methodParameter, @NotNull MethodParameter methodParameter,
@NotNull Type type, @NotNull Type type,
@NotNull Class<? extends HttpMessageConverter<?>> aClass) { @NotNull Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
return new DecryptRequestProtocol(httpInputMessage); return protocolSecurityService.decryptProtocol(httpInputMessage);
} }
/** /**

View File

@ -2,8 +2,8 @@ package com.dispose.interceptor;
import com.dispose.common.ProtoCryptoType; import com.dispose.common.ProtoCryptoType;
import com.dispose.common.SecurityConfigValue; import com.dispose.common.SecurityConfigValue;
import com.dispose.service.ProtocolSecurityService;
import com.security.annotation.Encryption; import com.security.annotation.Encryption;
import com.security.protocol.EncryptResponseProtocol;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
@ -14,6 +14,8 @@ import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import javax.annotation.Resource;
/** /**
* The type Response protocol security. * The type Response protocol security.
* *
@ -22,6 +24,13 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
@Slf4j @Slf4j
@RestControllerAdvice @RestControllerAdvice
public class ResponseProtocolSecurity implements ResponseBodyAdvice<Object> { public class ResponseProtocolSecurity implements ResponseBodyAdvice<Object> {
/**
* The Protocol security service.
*/
@Resource
private ProtocolSecurityService protocolSecurityService;
/** /**
* Supports boolean. * Supports boolean.
* *
@ -37,7 +46,7 @@ public class ResponseProtocolSecurity implements ResponseBodyAdvice<Object> {
} }
/** /**
* Before body write protocol resp dto. * Before body write object.
* *
* @param o the o * @param o the o
* @param methodParameter the method parameter * @param methodParameter the method parameter
@ -45,7 +54,7 @@ public class ResponseProtocolSecurity implements ResponseBodyAdvice<Object> {
* @param aClass the a class * @param aClass the a class
* @param serverHttpRequest the server http request * @param serverHttpRequest the server http request
* @param serverHttpResponse the server http response * @param serverHttpResponse the server http response
* @return the protocol resp dto * @return the object
*/ */
@Override @Override
@NotNull @NotNull
@ -55,11 +64,11 @@ public class ResponseProtocolSecurity implements ResponseBodyAdvice<Object> {
@NotNull Class<? extends HttpMessageConverter<?>> aClass, @NotNull Class<? extends HttpMessageConverter<?>> aClass,
@NotNull ServerHttpRequest serverHttpRequest, @NotNull ServerHttpRequest serverHttpRequest,
@NotNull ServerHttpResponse serverHttpResponse) { @NotNull ServerHttpResponse serverHttpResponse) {
if (SecurityConfigValue.SECURITY_PROTOCOL_TYPE == ProtoCryptoType.CRYPTO_NONE.getCode()) { if (SecurityConfigValue.SECURITY_PROTOCOL_TYPE == ProtoCryptoType.CRYPTO_NONE.getCode()) {
return o; return o;
} else { } else {
return new EncryptResponseProtocol(o, SecurityConfigValue.SECURITY_PROTOCOL_TYPE).toEncryptObject(); return protocolSecurityService.encryptProtocol(o, SecurityConfigValue.SECURITY_PROTOCOL_TYPE);
} }
} }
} }

View File

@ -0,0 +1,42 @@
package com.dispose.service;
import com.dispose.pojo.dto.protocol.base.ProtocolRespDTO;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.security.protocol.DecryptRequestProtocol;
import org.springframework.http.HttpInputMessage;
import java.io.IOException;
/**
* The interface Protocol security service.
*
* @author <huangxin@cmhi.chinamoblie.com>
*/
public interface ProtocolSecurityService {
/**
* Decrypt protocol string.
*
* @param ciphertext the ciphertext
* @return the string
* @throws JsonProcessingException the json processing exception
*/
String decryptProtocol(String ciphertext) throws JsonProcessingException;
/**
* Decrypt protocol decrypt request protocol.
*
* @param httpInputMessage the http input message
* @return the decrypt request protocol
* @throws IOException the io exception
*/
DecryptRequestProtocol decryptProtocol(HttpInputMessage httpInputMessage) throws IOException;
/**
* Encrypt protocol protocol resp dto.
*
* @param orgProtocol the org protocol
* @param cryptoType the crypto type
* @return the protocol resp dto
*/
ProtocolRespDTO<String> encryptProtocol(Object orgProtocol, int cryptoType);
}

View File

@ -0,0 +1,166 @@
package com.dispose.service.impl;
import com.dispose.common.ConstValue;
import com.dispose.common.ErrorCode;
import com.dispose.common.ProtoCryptoType;
import com.dispose.common.SecurityConfigValue;
import com.dispose.pojo.dto.protocol.base.ProtocolReqDTO;
import com.dispose.pojo.dto.protocol.base.ProtocolRespDTO;
import com.dispose.service.ProtocolSecurityService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.security.arithmetic.CryptoHelper;
import com.security.exception.SecurityProtocolException;
import com.security.protocol.DecryptRequestProtocol;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpInputMessage;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
/**
* The type Protocol security service.
*
* @author <huangxin@cmhi.chinamoblie.com>
*/
@Service
@Slf4j
public class ProtocolSecurityServiceImpl implements ProtocolSecurityService {
/**
* The Object mapper.
*/
@Resource
private ObjectMapper objectMapper;
/**
* Decrypt protocol string.
*
* @param ciphertext the ciphertext
* @return the string
* @throws JsonProcessingException the json processing exception
*/
@Override
public String decryptProtocol(String ciphertext) throws JsonProcessingException {
JsonNode objRoot = objectMapper.readTree(ciphertext);
int cryptoType = objRoot.path("cryptoType").asInt();
// 协议未加密
if (cryptoType == ProtoCryptoType.CRYPTO_NONE.getCode()) {
return ciphertext;
}
// 反序列化为对象处理
ProtocolReqDTO<String> proReq = objectMapper
.readValue(ciphertext, new TypeReference<ProtocolReqDTO<String>>(){});
// 首先对加密内容进行base64解码
byte[] base64Decode = CryptoHelper.base64Decryption(proReq.getMsgContent());
// 解密后的内容
byte[] decryptContent;
// 加密类型为base64直接返回处理结果
if (proReq.getCryptoType() == ProtoCryptoType.CRYPTO_BASE64.getCode()) {
decryptContent = base64Decode;
} else if (proReq.getCryptoType() == ProtoCryptoType.CRYPTO_AES256.getCode()) {
try {
decryptContent = CryptoHelper.aes256Decryption(base64Decode, SecurityConfigValue.AES_KEY);
} catch (Exception e) {
log.error("AES256 decode message error: {}", base64Decode);
throw new SecurityProtocolException(ErrorCode.ERR_DECRYPT_AES256);
}
} else if (proReq.getCryptoType() == ProtoCryptoType.CRYPTO_DES.getCode()) {
try {
decryptContent = CryptoHelper.desDecryption(base64Decode, SecurityConfigValue.DES_KEY);
} catch (Exception e) {
log.error("DES256 decode message error: {}", base64Decode);
throw new SecurityProtocolException(ErrorCode.ERR_DECRYPT_3DES);
}
} else {
log.error("Unknown protocol security type: {}, {}", proReq.getCryptoType(), ciphertext);
throw new SecurityProtocolException(ErrorCode.ERR_DECRYPT_UNKNOWN);
}
// 字节数组转换为字符串
String decodeMsg = new String(decryptContent, StandardCharsets.UTF_8);
return ciphertext.replace("\"" + proReq.getMsgContent() + "\"", decodeMsg);
}
/**
* Decrypt protocol decrypt request protocol.
*
* @param httpInputMessage the http input message
* @return the decrypt request protocol
* @throws IOException the io exception
*/
@Override
public DecryptRequestProtocol decryptProtocol(HttpInputMessage httpInputMessage) throws IOException {
// 提取协议中的JSON字符串
String reqMessage = IOUtils.toString(httpInputMessage.getBody(), StandardCharsets.UTF_8);
return new DecryptRequestProtocol(httpInputMessage, decryptProtocol(reqMessage));
}
/**
* Encrypt protocol protocol resp dto.
*
* @param orgProtocol the org protocol
* @param cryptoType the crypto type
* @return the protocol resp dto
*/
@Override
public ProtocolRespDTO<String> encryptProtocol(Object orgProtocol, int cryptoType) {
ProtocolRespDTO<String> cryptoObject = new ProtocolRespDTO<>();
cryptoObject.setVer(ConstValue.Protocol.VERSION);
cryptoObject.setCryptoType(SecurityConfigValue.SECURITY_PROTOCOL_TYPE);
cryptoObject.setTimeStamp(System.currentTimeMillis());
String msgContentJsonString;
try {
Method getMsgMethod = orgProtocol.getClass().getMethod("getMsgContent");
Method getCode = orgProtocol.getClass().getMethod("getCode");
msgContentJsonString = new ObjectMapper().writeValueAsString(getMsgMethod.invoke(orgProtocol));
cryptoObject.setCode((Integer) getCode.invoke(orgProtocol));
} catch (Exception e) {
log.error("Json encode message error: {}", orgProtocol);
throw new SecurityProtocolException(ErrorCode.ERR_SYSTEMEXCEPTION);
}
if (cryptoType == ProtoCryptoType.CRYPTO_BASE64.getCode()) {
cryptoObject.setMsgContent(CryptoHelper.base64Encryption(msgContentJsonString.getBytes(StandardCharsets.UTF_8)));
} else if (cryptoType == ProtoCryptoType.CRYPTO_AES256.getCode()) {
try {
byte[] encode = CryptoHelper.aes256Encryption(msgContentJsonString.getBytes(StandardCharsets.UTF_8),
SecurityConfigValue.AES_KEY);
cryptoObject.setMsgContent(CryptoHelper.base64Encryption(encode));
} catch (Exception e) {
log.error("AES256 encode message error: {}", msgContentJsonString);
throw new SecurityProtocolException(ErrorCode.ERR_DECRYPT_AES256);
}
} else if (cryptoType == ProtoCryptoType.CRYPTO_DES.getCode()) {
try {
byte[] encode = CryptoHelper.desEncryption(msgContentJsonString.getBytes(StandardCharsets.UTF_8),
SecurityConfigValue.DES_KEY);
cryptoObject.setMsgContent(CryptoHelper.base64Encryption(encode));
} catch (Exception e) {
log.error("DES256 encode message error: {}", msgContentJsonString);
throw new SecurityProtocolException(ErrorCode.ERR_DECRYPT_3DES);
}
} else {
log.error("Unknown protocol security type: {}, {}", cryptoType, msgContentJsonString);
throw new SecurityProtocolException(ErrorCode.ERR_ENCRYPT_UNKNOWN);
}
return cryptoObject;
}
}

View File

@ -1,14 +1,5 @@
package com.security.protocol; package com.security.protocol;
import com.dispose.common.ErrorCode;
import com.dispose.common.ProtoCryptoType;
import com.dispose.common.SecurityConfigValue;
import com.dispose.pojo.dto.protocol.base.ProtocolReqDTO;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.security.arithmetic.CryptoHelper;
import com.security.exception.SecurityProtocolException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
@ -16,7 +7,6 @@ import org.jetbrains.annotations.NotNull;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpInputMessage;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -28,87 +18,38 @@ import java.nio.charset.StandardCharsets;
@Slf4j @Slf4j
public class DecryptRequestProtocol implements HttpInputMessage { public class DecryptRequestProtocol implements HttpInputMessage {
/**
* The Object mapper.
*/
private final ObjectMapper objectMapper = new ObjectMapper();
/** /**
* The Input message. * The Input message.
*/ */
private final HttpInputMessage inputMessage; private final HttpInputMessage inputMessage;
/**
* The Msg content.
*/
private final String msgContent;
/** /**
* Instantiates a new Decrypt request protocol. * Instantiates a new Decrypt request protocol.
* *
* @param inputMessage the input message * @param inputMessage the input message
* @param msgContent the msg content
*/ */
@Contract(pure = true) @Contract(pure = true)
public DecryptRequestProtocol(HttpInputMessage inputMessage) { public DecryptRequestProtocol(HttpInputMessage inputMessage, String msgContent) {
this.inputMessage = inputMessage; this.inputMessage = inputMessage;
this.msgContent = msgContent;
} }
/** /**
* Gets body. * Gets body.
* *
* @return the body * @return the body
* @throws IOException the io exception
*/ */
@Override @Override
@NotNull @NotNull
public InputStream getBody() throws IOException { public InputStream getBody() {
// 解密后的内容
byte[] decryptContent;
// 提取协议中的JSON字符串
String reqMessage = IOUtils.toString(inputMessage.getBody(), StandardCharsets.UTF_8);
JsonNode objRoot = objectMapper.readTree(reqMessage);
int cryptoType = objRoot.path("cryptoType").asInt();
// 协议未加密
if (cryptoType == ProtoCryptoType.CRYPTO_NONE.getCode()) {
return IOUtils.toInputStream(reqMessage, StandardCharsets.UTF_8);
}
// 反序列化为对象处理
ProtocolReqDTO<String> proReq = objectMapper.readValue(reqMessage,
new TypeReference<ProtocolReqDTO<String>>() {
});
// 首先对加密内容进行base64解码
byte[] base64Decode = CryptoHelper.base64Decryption(proReq.getMsgContent());
// 加密类型为base64直接返回处理结果
if (proReq.getCryptoType() == ProtoCryptoType.CRYPTO_BASE64.getCode()) {
decryptContent = base64Decode;
} else if (proReq.getCryptoType() == ProtoCryptoType.CRYPTO_AES256.getCode()) {
try {
decryptContent = CryptoHelper.aes256Decryption(base64Decode, SecurityConfigValue.AES_KEY);
} catch (Exception e) {
log.error("AES256 decode message error: {}", base64Decode);
throw new SecurityProtocolException(ErrorCode.ERR_DECRYPT_AES256);
}
} else if (proReq.getCryptoType() == ProtoCryptoType.CRYPTO_DES.getCode()) {
try {
decryptContent = CryptoHelper.desDecryption(base64Decode, SecurityConfigValue.DES_KEY);
} catch (Exception e) {
log.error("DES256 decode message error: {}", base64Decode);
throw new SecurityProtocolException(ErrorCode.ERR_DECRYPT_3DES);
}
} else {
log.error("Unknown protocol security type: {}, {}", proReq.getCryptoType(), inputMessage.getBody());
throw new SecurityProtocolException(ErrorCode.ERR_DECRYPT_UNKNOWN);
}
// 字节数组转换为字符串
String decodeMsg = new String(decryptContent, StandardCharsets.UTF_8);
String decodeJson = reqMessage.replace("\"" + proReq.getMsgContent() + "\"", decodeMsg);
// 返回解密后的内容 // 返回解密后的内容
return IOUtils.toInputStream(decodeJson, StandardCharsets.UTF_8); return IOUtils.toInputStream(msgContent, StandardCharsets.UTF_8);
} }
/** /**

View File

@ -1,99 +0,0 @@
package com.security.protocol;
import com.dispose.common.ConstValue;
import com.dispose.common.ErrorCode;
import com.dispose.common.ProtoCryptoType;
import com.dispose.common.SecurityConfigValue;
import com.dispose.pojo.dto.protocol.base.ProtocolRespDTO;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.security.arithmetic.CryptoHelper;
import com.security.exception.SecurityProtocolException;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
/**
* The type Encrypt response protocol.
*
* @author <huangxin@cmhi.chinamoblie.com>
*/
@Slf4j
public class EncryptResponseProtocol {
/**
* The Object mapper.
*/
private final ObjectMapper objectMapper = new ObjectMapper();
/**
* The Object.
*/
private final Object object;
/**
* The Encrypt type.
*/
private final Integer encryptType;
/**
* Instantiates a new Encrypt response protocol.
*
* @param object the object
* @param encType the enc type
*/
public EncryptResponseProtocol(Object object, Integer encType) {
this.encryptType = encType;
this.object = object;
}
/**
* To encrypt object protocol resp dto.
*
* @return the protocol resp dto
*/
public ProtocolRespDTO<String> toEncryptObject() {
ProtocolRespDTO<String> cryptoObject = new ProtocolRespDTO<>();
cryptoObject.setVer(ConstValue.Protocol.VERSION);
cryptoObject.setCryptoType(SecurityConfigValue.SECURITY_PROTOCOL_TYPE);
cryptoObject.setTimeStamp(System.currentTimeMillis());
String msgContentJsonString;
try {
Method getMsgMethod = object.getClass().getMethod("getMsgContent");
Method getCode = object.getClass().getMethod("getCode");
msgContentJsonString = new ObjectMapper().writeValueAsString(getMsgMethod.invoke(object));
cryptoObject.setCode((Integer) getCode.invoke(object));
} catch (Exception e) {
log.error("Json encode message error: {}", object);
throw new SecurityProtocolException(ErrorCode.ERR_SYSTEMEXCEPTION);
}
if (encryptType == ProtoCryptoType.CRYPTO_BASE64.getCode()) {
cryptoObject.setMsgContent(CryptoHelper.base64Encryption(msgContentJsonString.getBytes(StandardCharsets.UTF_8)));
} else if (encryptType == ProtoCryptoType.CRYPTO_AES256.getCode()) {
try {
byte[] encode = CryptoHelper.aes256Encryption(msgContentJsonString.getBytes(StandardCharsets.UTF_8),
SecurityConfigValue.AES_KEY);
cryptoObject.setMsgContent(CryptoHelper.base64Encryption(encode));
} catch (Exception e) {
log.error("AES256 encode message error: {}", msgContentJsonString);
throw new SecurityProtocolException(ErrorCode.ERR_DECRYPT_AES256);
}
} else if (encryptType == ProtoCryptoType.CRYPTO_DES.getCode()) {
try {
byte[] encode = CryptoHelper.desEncryption(msgContentJsonString.getBytes(StandardCharsets.UTF_8),
SecurityConfigValue.DES_KEY);
cryptoObject.setMsgContent(CryptoHelper.base64Encryption(encode));
} catch (Exception e) {
log.error("DES256 encode message error: {}", msgContentJsonString);
throw new SecurityProtocolException(ErrorCode.ERR_DECRYPT_3DES);
}
} else {
log.error("Unknown protocol security type: {}, {}", encryptType, msgContentJsonString);
throw new SecurityProtocolException(ErrorCode.ERR_ENCRYPT_UNKNOWN);
}
return cryptoObject;
}
}