From 955778b3b91f6f74c17710145a702962c82bc27c Mon Sep 17 00:00:00 2001 From: HuangXin <huangxin@cmhi.chinamobile.com> Date: Wed, 26 Aug 2020 17:56:34 +0800 Subject: [PATCH] =?UTF-8?q?OCT=20REM:=201.=20=E5=A2=9E=E5=8A=A0=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=8D=8F=E8=AE=AE=E5=93=8D=E5=BA=94=E5=8A=A0=E5=AF=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=202.=20=E5=A2=9E=E5=8A=A0=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=93=8D=E5=BA=94=E5=8D=8F=E8=AE=AE=E5=8A=A0=E5=AF=86=E6=96=B9?= =?UTF-8?q?=E5=BC=8F=E7=9B=B8=E5=85=B3=E9=85=8D=E7=BD=AE=203.=20controller?= =?UTF-8?q?=20=E5=B1=82=E6=94=AF=E6=8C=81=E5=8D=8F=E8=AE=AE=E4=BC=A0?= =?UTF-8?q?=E8=BE=93=E5=8A=A0=E8=A7=A3=E5=AF=86=E5=8A=9F=E8=83=BD=204.=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=80=9A=E4=BF=A1=E5=8D=8F=E8=AE=AE=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/dispose/common/ErrorCode.java | 13 ++- .../dispose/controller/AuthController.java | 6 +- .../DisposeDeviceManagerController.java | 4 + ...rity.java => RequestProtocolSecurity.java} | 5 +- .../interceptor/ResponseProtocolSecurity.java | 65 ++++++++++++ .../dto/protocol/base/ProtocolRespDTO.java | 66 +++++-------- .../com/security/annotation/Decryption.java | 2 +- .../com/security/annotation/Encryption.java | 2 +- .../com/security/arithmetic/CryptoHelper.java | 29 +++++- .../protocol/EncryptResponseProtocol.java | 99 +++++++++++++++++++ 10 files changed, 239 insertions(+), 52 deletions(-) rename src/main/java/com/dispose/interceptor/{ProtocolSecurity.java => RequestProtocolSecurity.java} (93%) create mode 100644 src/main/java/com/dispose/interceptor/ResponseProtocolSecurity.java create mode 100644 src/main/java/com/security/protocol/EncryptResponseProtocol.java diff --git a/src/main/java/com/dispose/common/ErrorCode.java b/src/main/java/com/dispose/common/ErrorCode.java index 277b44a6..9eda310a 100644 --- a/src/main/java/com/dispose/common/ErrorCode.java +++ b/src/main/java/com/dispose/common/ErrorCode.java @@ -186,13 +186,22 @@ public enum ErrorCode { */ ERR_ENCRYPT_3DES(105, "3DES加密失败"), /** - * Err decrypt unknown error code. + * The Err decrypt unknown. */ ERR_DECRYPT_UNKNOWN(106, "不支持的解密算法"), /** - * Err encrypt unknown error code. + * The Err encrypt unknown. */ ERR_ENCRYPT_UNKNOWN(107, "不支持的加密算法"), + + /** + * Err json encode error code. + */ + ERR_JSON_ENCODE(108, "Json 序列号错误"), + /** + * Err json decode error code. + */ + ERR_JSON_DECODE(109, "Json 反序列化错误"), ; /** diff --git a/src/main/java/com/dispose/controller/AuthController.java b/src/main/java/com/dispose/controller/AuthController.java index fd7f6fff..4f0ca880 100644 --- a/src/main/java/com/dispose/controller/AuthController.java +++ b/src/main/java/com/dispose/controller/AuthController.java @@ -11,6 +11,7 @@ import com.dispose.pojo.dto.protocol.base.ValidGroups; import com.dispose.pojo.po.MulReturnType; import com.dispose.service.UserAccountService; import com.security.annotation.Decryption; +import com.security.annotation.Encryption; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; @@ -38,6 +39,8 @@ import java.security.NoSuchAlgorithmException; @Api(value = "处置平台认证接口", tags = "处置平台认证接口") @Component @Validated +@Encryption +@Decryption public class AuthController { /** * The User account service. @@ -55,7 +58,7 @@ public class AuthController { @PostMapping("/login") @ResponseBody @ApiOperation("登录") - public ProtocolRespDTO<? extends BaseRespStatus> userLogin(@Decryption + public ProtocolRespDTO<? extends BaseRespStatus> userLogin( @Validated(ValidGroups.LoginReqValid.class) @RequestBody ProtocolReqDTO<LoginReq> mr) throws NoSuchAlgorithmException { @@ -95,6 +98,7 @@ public class AuthController { @PostMapping("/logout") @ResponseBody @ApiOperation("注销") + @Encryption public ProtocolRespDTO<? extends BaseRespStatus> userLogout(@Validated(ValidGroups.LogoutReqValid.class) @RequestBody ProtocolReqDTO<LoginReq> mr, @RequestHeader HttpHeaders headers) { // 注销用户登录 diff --git a/src/main/java/com/dispose/controller/DisposeDeviceManagerController.java b/src/main/java/com/dispose/controller/DisposeDeviceManagerController.java index d017f8d5..922a0134 100644 --- a/src/main/java/com/dispose/controller/DisposeDeviceManagerController.java +++ b/src/main/java/com/dispose/controller/DisposeDeviceManagerController.java @@ -27,6 +27,8 @@ import com.dispose.pojo.entity.DisposeDevice; import com.dispose.pojo.po.MulReturnType; import com.dispose.service.DisposeDeviceManagerService; import com.github.pagehelper.PageInfo; +import com.security.annotation.Decryption; +import com.security.annotation.Encryption; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; @@ -55,6 +57,8 @@ import java.util.List; @Api(value = "处置平台设备管理接口", tags = "处置平台设备管理接口") @Component @Validated +@Encryption +@Decryption public class DisposeDeviceManagerController { /** diff --git a/src/main/java/com/dispose/interceptor/ProtocolSecurity.java b/src/main/java/com/dispose/interceptor/RequestProtocolSecurity.java similarity index 93% rename from src/main/java/com/dispose/interceptor/ProtocolSecurity.java rename to src/main/java/com/dispose/interceptor/RequestProtocolSecurity.java index 94177a61..c9e1dd03 100644 --- a/src/main/java/com/dispose/interceptor/ProtocolSecurity.java +++ b/src/main/java/com/dispose/interceptor/RequestProtocolSecurity.java @@ -19,7 +19,7 @@ import java.lang.reflect.Type; */ @Slf4j @RestControllerAdvice -public class ProtocolSecurity implements RequestBodyAdvice { +public class RequestProtocolSecurity implements RequestBodyAdvice { /** * Supports boolean. * @@ -32,7 +32,8 @@ public class ProtocolSecurity implements RequestBodyAdvice { public boolean supports(@NotNull MethodParameter methodParameter, @NotNull Type type, @NotNull Class<? extends HttpMessageConverter<?>> aClass) { - return methodParameter.hasParameterAnnotation(Decryption.class); + return methodParameter.getContainingClass().isAnnotationPresent(Decryption.class) + || methodParameter.hasMethodAnnotation(Decryption.class); } /** diff --git a/src/main/java/com/dispose/interceptor/ResponseProtocolSecurity.java b/src/main/java/com/dispose/interceptor/ResponseProtocolSecurity.java new file mode 100644 index 00000000..02c4a2af --- /dev/null +++ b/src/main/java/com/dispose/interceptor/ResponseProtocolSecurity.java @@ -0,0 +1,65 @@ +package com.dispose.interceptor; + +import com.dispose.common.ProtoCryptoType; +import com.dispose.common.SecurityConfigValue; +import com.security.annotation.Encryption; +import com.security.protocol.EncryptResponseProtocol; +import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; +import org.springframework.core.MethodParameter; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; + +/** + * The type Response protocol security. + * + * @author <huangxin@cmhi.chinamoblie.com> + */ +@Slf4j +@RestControllerAdvice +public class ResponseProtocolSecurity implements ResponseBodyAdvice<Object> { + /** + * Supports boolean. + * + * @param methodParameter the method parameter + * @param aClass the a class + * @return the boolean + */ + @Override + public boolean supports(@NotNull MethodParameter methodParameter, + @NotNull Class<? extends HttpMessageConverter<?>> aClass) { + return methodParameter.getContainingClass().isAnnotationPresent(Encryption.class) + || methodParameter.hasMethodAnnotation(Encryption.class); + } + + /** + * Before body write protocol resp dto. + * + * @param o the o + * @param methodParameter the method parameter + * @param mediaType the media type + * @param aClass the a class + * @param serverHttpRequest the server http request + * @param serverHttpResponse the server http response + * @return the protocol resp dto + */ + @Override + @NotNull + public Object beforeBodyWrite(Object o, + @NotNull MethodParameter methodParameter, + @NotNull MediaType mediaType, + @NotNull Class<? extends HttpMessageConverter<?>> aClass, + @NotNull ServerHttpRequest serverHttpRequest, + @NotNull ServerHttpResponse serverHttpResponse) { + + if (SecurityConfigValue.SECURITY_PROTOCOL_TYPE == ProtoCryptoType.CRYPTO_NONE.getCode()) { + return o; + } else { + return new EncryptResponseProtocol(o, SecurityConfigValue.SECURITY_PROTOCOL_TYPE).toEncryptObject(); + } + } +} diff --git a/src/main/java/com/dispose/pojo/dto/protocol/base/ProtocolRespDTO.java b/src/main/java/com/dispose/pojo/dto/protocol/base/ProtocolRespDTO.java index 3d64ced8..50f29271 100644 --- a/src/main/java/com/dispose/pojo/dto/protocol/base/ProtocolRespDTO.java +++ b/src/main/java/com/dispose/pojo/dto/protocol/base/ProtocolRespDTO.java @@ -2,7 +2,7 @@ package com.dispose.pojo.dto.protocol.base; import com.dispose.common.ConstValue; import com.dispose.common.ErrorCode; -import com.dispose.common.ProtoCryptoType; +import com.dispose.common.SecurityConfigValue; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.annotations.ApiModelProperty; @@ -10,6 +10,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; /** * The type Protocol resp dto. @@ -17,6 +18,7 @@ import lombok.NoArgsConstructor; * @param <T> the type parameter * @author <huangxin@cmhi.chinamoblie.com> */ +@Slf4j @EqualsAndHashCode(callSuper = true) @Data @NoArgsConstructor @@ -29,7 +31,7 @@ public class ProtocolRespDTO<T> extends BaseProtocolDTO<T> { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); /** - * 状态码,用于记录服务器返回状态信息,例如HTTP返回值等. + * The Code. */ @ApiModelProperty(value = "服务器返回状态码", example = "200") private Integer code; @@ -37,13 +39,21 @@ public class ProtocolRespDTO<T> extends BaseProtocolDTO<T> { /** * Result protocol resp dto. * - * @param <T> the type parameter - * @param err the err - * @param obj the obj + * @param <T> the type parameter + * @param err the err + * @param httpCode the http code + * @param respMsg the resp msg * @return the protocol resp dto */ - public static <T> ProtocolRespDTO<T> result(ErrorCode err, T obj) { - return result(err, obj, ProtoCryptoType.CRYPTO_NONE.getCode()); + private static <T> ProtocolRespDTO<T> result(ErrorCode err, Integer httpCode, T respMsg) { + ProtocolRespDTO<T> resp = new ProtocolRespDTO<>(); + + resp.setVer(ConstValue.Protocol.VERSION); + resp.setCode(httpCode); + resp.setCryptoType(SecurityConfigValue.SECURITY_PROTOCOL_TYPE); + resp.setTimeStamp(System.currentTimeMillis()); + resp.setMsgContent(respMsg); + return resp; } /** @@ -52,19 +62,10 @@ public class ProtocolRespDTO<T> extends BaseProtocolDTO<T> { * @param <T> the type parameter * @param err the err * @param respMsg the resp msg - * @param crypto the crypto * @return the protocol resp dto */ - public static <T> ProtocolRespDTO<T> result(ErrorCode err, T respMsg, Integer crypto) { - ProtocolRespDTO<T> resp = new ProtocolRespDTO<>(); - - resp.setVer(ConstValue.Protocol.VERSION); - resp.setCode(err.getHttpCode()); - resp.setCryptoType(crypto); - resp.setTimeStamp(System.currentTimeMillis()); - resp.setMsgContent(respMsg); - - return resp; + public static <T> ProtocolRespDTO<T> result(ErrorCode err, T respMsg) { + return result(err, err.getHttpCode(), respMsg); } /** @@ -74,19 +75,8 @@ public class ProtocolRespDTO<T> extends BaseProtocolDTO<T> { * @return the protocol resp dto */ public static ProtocolRespDTO<BaseRespStatus> result(ErrorCode err) { - - ProtocolRespDTO<BaseRespStatus> resp = new ProtocolRespDTO<>(); - BaseRespStatus rspMsg = new BaseRespStatus(); - rspMsg.setStatus(err.getCode()); - rspMsg.setMessage(new String[] {err.getMsg()}); - - resp.setVer(ConstValue.Protocol.VERSION); - resp.setCode(err.getHttpCode()); - resp.setCryptoType(ProtoCryptoType.CRYPTO_NONE.getCode()); - resp.setTimeStamp(System.currentTimeMillis()); - resp.setMsgContent(rspMsg); - - return resp; + BaseRespStatus rspMsg = new BaseRespStatus(err.getCode(), new String[]{err.getMsg()}); + return result(err, err.getHttpCode(), rspMsg); } /** @@ -98,17 +88,7 @@ public class ProtocolRespDTO<T> extends BaseProtocolDTO<T> { * @return the protocol resp dto */ public static ProtocolRespDTO<BaseRespStatus> result(ErrorCode errCode, Integer httpCode, String[] message) { - ProtocolRespDTO<BaseRespStatus> resp = new ProtocolRespDTO<>(); - BaseRespStatus rspMsg = new BaseRespStatus(); - rspMsg.setStatus(errCode.getCode()); - rspMsg.setMessage(message); - - resp.setVer(ConstValue.Protocol.VERSION); - resp.setCode(httpCode); - resp.setCryptoType(ProtoCryptoType.CRYPTO_NONE.getCode()); - resp.setTimeStamp(System.currentTimeMillis()); - resp.setMsgContent(rspMsg); - - return resp; + BaseRespStatus rspMsg = new BaseRespStatus(errCode.getCode(), message); + return result(errCode, httpCode, rspMsg); } } diff --git a/src/main/java/com/security/annotation/Decryption.java b/src/main/java/com/security/annotation/Decryption.java index da724a7b..ff7e637f 100644 --- a/src/main/java/com/security/annotation/Decryption.java +++ b/src/main/java/com/security/annotation/Decryption.java @@ -10,7 +10,7 @@ import java.lang.annotation.Target; * * @author <huangxin@cmhi.chinamoblie.com> */ -@Target({ElementType.PARAMETER, ElementType.METHOD}) +@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Decryption { } diff --git a/src/main/java/com/security/annotation/Encryption.java b/src/main/java/com/security/annotation/Encryption.java index 17c83056..0b6e38f3 100644 --- a/src/main/java/com/security/annotation/Encryption.java +++ b/src/main/java/com/security/annotation/Encryption.java @@ -10,7 +10,7 @@ import java.lang.annotation.Target; * * @author <huangxin@cmhi.chinamoblie.com> */ -@Target({ElementType.PARAMETER, ElementType.METHOD}) +@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Encryption { } diff --git a/src/main/java/com/security/arithmetic/CryptoHelper.java b/src/main/java/com/security/arithmetic/CryptoHelper.java index 9f45da54..2ac8652f 100644 --- a/src/main/java/com/security/arithmetic/CryptoHelper.java +++ b/src/main/java/com/security/arithmetic/CryptoHelper.java @@ -73,8 +73,8 @@ public class CryptoHelper { /** * Aes 256 encryption byte [ ]. * - * @param plaintext the ciphertext - * @param aesKey the aes key + * @param plaintext the plaintext + * @param aesKey the aes key * @return the byte [ ] * @throws NoSuchAlgorithmException the no such algorithm exception * @throws NoSuchPaddingException the no such padding exception @@ -145,4 +145,29 @@ public class CryptoHelper { cipher.init(Cipher.ENCRYPT_MODE, secretKey, sr); return cipher.doFinal(ciphertext); } + + /** + * Des encryption byte [ ]. + * + * @param plaintext the plaintext + * @param desKey the des key + * @return the byte [ ] + * @throws InvalidKeyException the invalid key exception + * @throws NoSuchAlgorithmException the no such algorithm exception + * @throws InvalidKeySpecException the invalid key spec exception + * @throws NoSuchPaddingException the no such padding exception + * @throws BadPaddingException the bad padding exception + * @throws IllegalBlockSizeException the illegal block size exception + */ + public static byte[] desEncryption(byte[] plaintext, String desKey) throws InvalidKeyException, + NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, BadPaddingException, + IllegalBlockSizeException { + SecureRandom sr = new SecureRandom(); + DESKeySpec desKeySpec = new DESKeySpec(desKey.getBytes()); + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); + SecretKey secretKey = keyFactory.generateSecret(desKeySpec); + Cipher cipher = Cipher.getInstance(DES_ALGORITHM_STR); + cipher.init(Cipher.DECRYPT_MODE, secretKey, sr); + return cipher.doFinal(plaintext); + } } diff --git a/src/main/java/com/security/protocol/EncryptResponseProtocol.java b/src/main/java/com/security/protocol/EncryptResponseProtocol.java new file mode 100644 index 00000000..a146de3d --- /dev/null +++ b/src/main/java/com/security/protocol/EncryptResponseProtocol.java @@ -0,0 +1,99 @@ +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; + } +}