哈尔滨大型网站建设电话,企业展厅建设的原则,公司注册资金认缴和实缴区别,长沙市网站制作哪家专业一、前言 在实际项目开发中#xff0c;可能会涉及到一些敏感信息#xff0c;那么我们就需要对这些敏感信息进行加密处理#xff0c; 也就是脱敏#xff0c;比如像手机号、身份证号等信息。如果我们只是在接口返回后再去做替换处理#xff0c;则代码会显得非常冗余#xf…一、前言 在实际项目开发中可能会涉及到一些敏感信息那么我们就需要对这些敏感信息进行加密处理 也就是脱敏比如像手机号、身份证号等信息。如果我们只是在接口返回后再去做替换处理则代码会显得非常冗余那么实际可以通过注解的方式实现数据脱敏。
二、具体实现 1.定义一个标记于方法上的注解。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;Target(ElementType.METHOD) //METHOD 说明该注解只能用在方法上
Retention(RetentionPolicy.RUNTIME) //RUNTIME 说明该注解在运行时生效
public interface DataEncryption {}
2.定义一个数据解密的注解。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;Target(ElementType.METHOD) //METHOD 说明该注解只能用在方法上
Retention(RetentionPolicy.RUNTIME) //RUNTIME 说明该注解在运行时生效
public interface DataDecryption {}3.定义一个在字段上且有值的注解。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;Target(ElementType.FIELD) //FIELD 说明该注解只能用在字段上
Retention(RetentionPolicy.RUNTIME) //RUNTIME 说明该注解在运行时生效
public interface EncryptField {//脱敏枚举值DesensitizationEnum value();
}
4.定义一个在字段上且有值的注解。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;Target(ElementType.FIELD) //FIELD 说明该注解只能用在字段上
Retention(RetentionPolicy.RUNTIME) //RUNTIME 说明该注解在运行时生效
public interface DecryptField {//脱敏枚举值DesensitizedUtil.DesensitizedType value();
}5.定义用户返回的实体类。 import com.test.annotation.DecryptField;
import com.test.enums.DesensitizationEnum;
import com.test.utils.AesUtil;import java.lang.reflect.Field;
import lombok.Data;
// 用户信息返回实体类
Data
public class UserResVo {DecryptField(DesensitizedUtil.DesensitizedType.CHINESE_NAME)EncryptFieldprivate String name;EncryptFieldEncryptField(DesensitizedUtil.DesensitizedType.ID_CARD)private String idCard;EncryptFieldEncryptField(DesensitizedUtil.DesensitizedType.MOBILE_PHONE)private String phone;EncryptFieldEncryptField(DesensitizedUtil.DesensitizedType.EMAIL)private String email;
}
6.定义AOP注解实现
import cn.hutool.crypto.digest.DigestUtil;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.util.Objects;Aspect
Component
Slf4j
public class SecretAopAspect {Pointcut(annotation(com.secret.annotation.DataEncryption))public void encryptAopCut() {}Pointcut(annotation(com.secret.annotation.DataDecryption))public void decryptAopCut() {}/*** method encryptMethodAop* desc 加密方法* Param: joinPoint*/Around(encryptAopCut())public Object encryptMethodAop(ProceedingJoinPoint joinPoint) {Object responseObj null;try {responseObj joinPoint.proceed();this.handleEncrypt(responseObj);//md5加密在相应里面设置签名值String md5Data DigestUtil.md5Hex(new Gson().toJson(responseObj));HttpServletResponse response ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();response.setHeader(md5,md5Data);} catch (Throwable throwable) {throwable.printStackTrace();this.log.error(encryptMethodAop处理出现异常{}, throwable);}return responseObj;}/*** method decryptMethodAop* desc 解密方法* Param: joinPoint*/Around(decryptAopCut())public Object decryptMethodAop(ProceedingJoinPoint joinPoint) {Object responseObj null;try {responseObj joinPoint.getArgs()[0];//throw new RuntimeException(md5校验失败);this.handleDecrypt(responseObj);//生成md5签名String md5 DigestUtil.md5Hex(new Gson().toJson(responseObj));System.out.println(md5);//从请求头获取前端传过来的签名String origianlMd5 ;HttpServletRequest request ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();origianlMd5 request.getHeader(md5);//比对签名if(md5.equals(origianlMd5)){//方便调试不比对前端签名responseObj joinPoint.proceed();}else{throw new Exception(参数的md5校验不同可能存在篡改行为请检查);}} catch (Throwable throwable) {throwable.printStackTrace();log.error(decryptMethodAop处理出现异常{}, throwable);}return responseObj;}/*** method handleEncrypt* desc 对实体么个属性进行加密* Param: requestObj* return void*/private void handleEncrypt(Object requestObj) throws Exception {if (!Objects.isNull(requestObj)) {Field[] fields requestObj.getClass().getDeclaredFields();Field[] fieldsCopy fields;int fieldLength fields.length;for(int i 0; i fieldLength; i) {Field field fieldsCopy[i];boolean hasSecureField field.isAnnotationPresent(EncryptField.class);if (hasSecureField) {field.setAccessible(true);String plaintextValue (String)field.get(requestObj);String cipherText AesUtil.encrypt(plaintextValue);field.set(requestObj, cipherText);}}}}/*** method handleDecrypt* desc 对实体么个属性进行解密* Param: responseObj* return*/private Object handleDecrypt(Object responseObj) throws Exception {if (Objects.isNull(responseObj)) {return null;} else {Field[] fields responseObj.getClass().getDeclaredFields();Field[] fieldsCopy fields;int fieldLength fields.length;for(int i 0; i fieldLength; i) {Field field fieldsCopy[i];boolean hasSecureField field.isAnnotationPresent(DecryptField.class);if (hasSecureField) {DecryptField decryptField field.getAnnotation(DecryptField.class);field.setAccessible(true);String encryptValue (String)field.get(responseObj);encryptValue AesUtil.decrypt(encryptValue,decryptField.getValue());field.set(responseObj, encryptValue);}}return responseObj;}}}7.加解密工具类
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;public class AesUtil {// 默认16位 或 128 256位public static String AES_KEY EN#qerdfdshbd110;public static AES aes SecureUtil.aes(AES_KEY.getBytes());public static String encrypt(Object obj) {return aes.encryptHex((String) obj);}public static String decrypt(Object obj, DesensitizedUtil.DesensitizedType desensitizedType) {// 解密String decrypt decrypt(obj);// 脱敏return DesensitizedUtil.desensitized(decrypt, desensitizedType);}public static String decrypt(Object obj) {return aes.decryptStr((String) obj, CharsetUtil.CHARSET_UTF_8);}
}8.接着就可以测试了。