Java 数据加密解密及脱敏处理

Java 数据加密解密及脱敏处理

(一)实现效果 (注解自动加密解密)

(1) 解密 impl类加注解

在这里插入图片描述
返回VO实体类中加注释
在这里插入图片描述

(2) 加密 controller 解密注解 @Encryption

在这里插入图片描述
入参实体类 加密注解 @EncryptField
在这里插入图片描述

(3)也可以单独调用加密或解密

// 明文单独调用加密
String	phoneNums = AesUtil.encryptString(phoneNum);
// 明文单独调用脱敏
s.setLegalPhone(AesUtil.desensitization(s.getLegalPhone(), DesensitizationEnum.phoneNum));
// 密文解密成明文单独调用
AesUtil.decryptString(query.getKeywords()))

加密、解密

加密DTO类
@EncryptField

加密Controller
@Encryption

解密加脱敏 VO类
@DecryptField(DesensitizationEnum.idCard)
解密明文
@DecryptField(DesensitizationEnum.isPlaintext)
解密Controller
@Decryption

(4) 前端显示解密脱敏效果

在这里插入图片描述

(5) 数据库字段加密后效果

在这里插入图片描述

(二) 准备基础类

(1) 拦截需解密注解类 DecryptAspect

@Slf4j
@Aspect
@Component
public class DecryptAspect {
	//拦截需解密注解
	@Pointcut("@annotation(com.wangyao.remote.desensitization.Decryption)")
	public void point() {

	}

	@Around("point()")
	public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
		//解密
		return decrypt(joinPoint);
	}

	public Object decrypt(ProceedingJoinPoint joinPoint) {
		Object result = null;
		try {
			Object obj = joinPoint.proceed();
			if (obj != null) {
				//可自行扩展其他类型字段的判断
				if (obj instanceof String) {
					decryptValue();
				}else if(obj instanceof ArrayList) {
					decryptList(obj);
					result = obj;
				}else if(obj instanceof ServerResponseEntity){
					if(((ServerResponseEntity<?>) obj).getData() instanceof PageVO) {
						List<?> items = ((PageVO<?>) ((ServerResponseEntity<?>) obj).getData()).getList();
						Object s = decryptData(items);
						JSON.parseArray( JSON.toJSONString(s), ((PageVO<?>) ((ServerResponseEntity<?>) obj).getData()).getList().getClass());
						result = obj;
					} else if(((ServerResponseEntity<?>) obj).getData() instanceof EsPageVO){
						List<?> items = ((EsPageVO<?>) ((ServerResponseEntity<?>) obj).getData()).getList();
						Object s = decryptData(items);
						JSON.parseArray( JSON.toJSONString(s), ((EsPageVO<?>) ((ServerResponseEntity<?>) obj).getData()).getList().getClass());
						result = obj;
					} else {
						Object s = decryptData(((ServerResponseEntity<?>) obj).getData());
						JSON.parseArray( JSON.toJSONString(s), (((ServerResponseEntity<?>) obj).getData()).getClass());
						result = obj;
					}
				}else if(obj instanceof PageVO){
					List<?> items = ((PageVO<?>) (obj)).getList();
					Object s = decryptData(items);
					JSON.parseArray( JSON.toJSONString(s), ((PageVO<?>) (obj)).getList().getClass());
					result = obj;
				}else if(obj instanceof List){
					List<?> items =(List)(obj);
					Object s = decryptData(items);
					JSON.parseArray( JSON.toJSONString(s), ((List) (obj)).getClass());
					result = obj;
				}else {
					result = decryptData(obj);
				}
			}
		} catch (Throwable e) {
			e.printStackTrace();
		}
		return result;
	}

	private Object decryptData(Object obj) throws IllegalAccessException {
		if (Objects.isNull(obj)) {
			return null;
		}
		if (obj instanceof ArrayList) {
			decryptList(obj);
		}else {
			decryptObj(obj);
		}
		return obj;
	}

	private void decryptObj(Object obj) throws IllegalAccessException {
		Field[] fields = obj.getClass().getDeclaredFields();
		for (Field field : fields) {
			boolean hasSecureField = field.isAnnotationPresent(DecryptField.class);
			if (hasSecureField) {
				field.setAccessible(true);
				if (field.get(obj) != null) {
					String realValue = (String) field.get(obj);
					if(realValue.length()>30){
						DesensitizationEnum desensitizationEnum = field.getAnnotation(DecryptField.class).value();
						String value = (String) AesUtil.decrypt(realValue,desensitizationEnum);
						field.set(obj, value);
					}else {
						field.set(obj, realValue);
					}

				}
			}
		}
	}

	private void decryptList(Object obj) throws IllegalAccessException {
		List<Object> result = new ArrayList<>();
		if (obj instanceof ArrayList) {
			result.addAll((Collection<?>) obj);
		}
		for (Object object : result) {
			decryptObj(object);
		}
	}

	private void decryptValue() {
		log.info("根据对象进行解密脱敏,单个字段不做处理!");
	}
}

(2) 数据脱敏注解类(用在实体类上) DecryptField

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DecryptField {
	DesensitizationEnum value();
}

(3) 解密 注解类 (用在方法上) Decryption

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Decryption {
}

(4) 脱敏枚举 DesensitizationEnum

public enum DesensitizationEnum {
	/**
	 * 明文 不隐藏
	 */
	isPlaintext,
	/**
	 * 通用 前3 后2  其他隐藏
	 */
	current,
	/**
	 * 手机号
	 */
	phoneNum,
	/**
	 * 地址
	 */
	address,
	/**
	 * 身份证号
	 */
	idCard,
	/**
	 * 银行卡号
	 */
	bankCard,
	/**
	 * 名称
	 */
	name,
	/**
	 * 邮箱
	 */
	email,
}

(5) 脱敏实现类 DesensitizationUtil

public class DesensitizationUtil {
	public static Object desensitization(Object obj, DesensitizationEnum desensitizationEnum) {
		Object result;
		switch (desensitizationEnum) {
			case name:
				result = strUtilHide(obj, 1);
				break;
			case address:
				result = strUtilHide(obj, 3);
				break;
			case phoneNum:
				result = mobilePhone((String)obj);
				break;
			case idCard:
				result = idCardNum((String)obj);
				break;
			case current:      // 通用
				result = current((String)obj);
				break;
			case isPlaintext:  // 明文
				result = (String)obj;
				break;
			default:
				result = "";
		}
		return result;
	}

	/**
	 * start从0开始
	 */
	public static Object strUtilHide(String obj, int start, int end) {
		return StrUtil.hide(obj, start, end);
	}

	public static Object strUtilHide(Object obj, int start) {
		return strUtilHide(((String) obj), start, ((String) obj).length());
	}

	/**
	 * 对字符串进行脱敏操作
	 *
	 * @param origin          原始字符串
	 * @param prefixNoMaskLen 左侧需要保留几位明文字段
	 * @param suffixNoMaskLen 右侧需要保留几位明文字段
	 * @param maskStr         用于遮罩的字符串, 如'*'
	 * @return 脱敏后结果
	 */
	public static String desValue(String origin, int prefixNoMaskLen, int suffixNoMaskLen, String maskStr) {
		if (origin == null) {
			return null;
		}

		StringBuilder sb = new StringBuilder();
		for (int i = 0, n = origin.length(); i < n; i++) {
			if (i < prefixNoMaskLen) {
				sb.append(origin.charAt(i));
				continue;
			}
			if (i > (n - suffixNoMaskLen - 1)) {
				sb.append(origin.charAt(i));
				continue;
			}
			sb.append(maskStr);
		}
		return sb.toString();
	}
	/**
	 * 【中文姓名】只显示最后一个汉字,其他隐藏为星号,比如:**梦
	 *
	 * @param fullName 姓名
	 * @return 结果
	 */
	public static String chineseName(String fullName) {
		if (fullName == null) {
			return null;
		}
		return desValue(fullName, 1, 0, "*");
	}

	/**
	 * 【身份证号】显示前4位, 后2位,其他隐藏。
	 *
	 * @param id 身份证号码
	 * @return 结果
	 */
	public static String idCardNum(String id) {
		return desValue(id, 4, 2, "*");
	}

	/**
	 * 【手机号码】前三位,后四位,其他隐藏。
	 *
	 * @param num 手机号码
	 * @return 结果
	 */
	public static String mobilePhone(String num) {
		return desValue(num, 3, 4, "*");
	}

	/**
	 * 通用 前3 后2  其他隐藏
	 */
	public static String current(String num) {
		return desValue(num, 3, 2, "*");
	}
}

(6) 拦截需加密注解 类 EncryptAspect

@Slf4j
@Aspect
@Component
public class EncryptAspect {
	//拦截需加密注解
	@Pointcut("@annotation(com.wangyao.remote.desensitization.Encryption)")
	public void point() {

	}

	@Around("point()")
	public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
		//加密
		encrypt(joinPoint);
		return joinPoint.proceed();
	}

	public void encrypt(ProceedingJoinPoint joinPoint) {
		Object[] objects;
		try {
			objects = joinPoint.getArgs();
			if (objects.length != 0) {
				for (Object object : objects) {
					Field[] fields = object.getClass().getDeclaredFields();
					for (Field field : fields) {
						if (field.isAnnotationPresent(EncryptField.class)) {
							field.setAccessible(true);
							if (field.get(object) != null) {
								// 进行加密
								Object encrypt = AesUtil.encrypt(field.get(object));
								field.set(object, encrypt);
							}
						}
					}
				}
			}
		} catch (Exception e) {
			log.error(e.getMessage());
		}
	}
}

(7) 数据加密 注解(用在实体类上) EncryptField

@Target(ElementType.FIELD)           //FIELD 说明该注解只能用在字段上
@Retention(RetentionPolicy.RUNTIME)  //RUNTIME 说明该注解在运行时生效
public @interface EncryptField {
}

(8) 方法解密(用在方法上)

// METHOD 说明该注解只能用在方法上
// RUNTIME 说明该注解在运行时生效
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface  Encryption {
}

(三) 加密方法 AES

public class AesUtil {
	// 默认16位 或 128 256位
//	public static String AES_KEY = "AWk#SqerdSSfdsSShbSd910";

//	public static AES aes = SecureUtil.aes(AES_KEY.getBytes());
	public static AES aes = SecureUtil.aes("AWk#qerdfdshbd910".getBytes());

	public static Object encrypt(Object obj) {
		return aes.encryptHex((String) obj);
	}

	public static Object decrypt(Object obj, DesensitizationEnum desensitizationEnum) {
		// 解密
		Object decrypt = decrypt(obj);
		// 脱敏
		return DesensitizationUtil.desensitization(decrypt, desensitizationEnum);
	}

	public static Object decrypt(Object obj) {
		return aes.decryptStr((String) obj, CharsetUtil.CHARSET_UTF_8);
	}

	// 加密
	public static String encryptString(String str) {
		return aes.encryptHex(str);
	}
	// 解密
	public static String decryptString(String str) {
		return aes.decryptStr(str, CharsetUtil.CHARSET_UTF_8);
	}

	// 解密+脱敏 返回字符串
	public static String decryptStringDesensitization(String str, DesensitizationEnum desensitizationEnum) {
		// 解密
		String decrypt = decryptString(str);
		// 脱敏
		Object object = decrypt;
		return DesensitizationUtil.desensitization(object, desensitizationEnum).toString();
	}

	// 字符串脱敏
	public static String desensitization(String str, DesensitizationEnum desensitizationEnum) {
		// 脱敏
		return DesensitizationUtil.desensitization(str, desensitizationEnum).toString();
	}

	// 加密集合
	public static List<String> encryptStringList(List<String> str) {
		return str.stream().map(m->aes.encryptHex(m)).collect(Collectors.toList());
	}

	// 判断是否包含中文
	public static boolean containsChineseCharacters(String str) {
		if (str == null) {
			return false;
		}
		return str.chars().anyMatch(c -> isChineseCharacter((char) c));
	}
	public static boolean isChineseCharacter(char c) {
		Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
		return ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
				|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
				|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
				|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
				|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
				|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
				|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION;
	}


	public static void main(String[] args) {
		String s = "d2528630b2ccbd3f12c979e0cc2754f3";
		System.out.println(decryptString(s));
	}
}
  • 17
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Java提供了很多加密算法,可以用于加密和解密jar文件。常用的加密算法有AES、DES、RSA等。 下面是一个使用AES算法对jar文件进行加密和解密的示例代码: ```java import java.io.*; import java.security.*; import javax.crypto.*; import javax.crypto.spec.*; public class JarEncryptor { private static final String ALGO = "AES"; private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding"; private static final byte[] IV = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; public static void encrypt(String key, File inputFile, File outputFile) throws Exception { doCrypto(Cipher.ENCRYPT_MODE, key, inputFile, outputFile); } public static void decrypt(String key, File inputFile, File outputFile) throws Exception { doCrypto(Cipher.DECRYPT_MODE, key, inputFile, outputFile); } private static void doCrypto(int cipherMode, String key, File inputFile, File outputFile) throws Exception { Key secretKey = new SecretKeySpec(key.getBytes(), ALGO); Cipher cipher = Cipher.getInstance(TRANSFORMATION); IvParameterSpec iv = new IvParameterSpec(IV); cipher.init(cipherMode, secretKey, iv); FileInputStream inputStream = new FileInputStream(inputFile); byte[] inputBytes = new byte[(int) inputFile.length()]; inputStream.read(inputBytes); byte[] outputBytes = cipher.doFinal(inputBytes); FileOutputStream outputStream = new FileOutputStream(outputFile); outputStream.write(outputBytes); inputStream.close(); outputStream.close(); } } ``` 在上面的代码中,我们使用AES算法和CBC模式对jar文件进行加密和解密。加密和解密的关键是密钥,我们需要提供一个密钥来进行加密和解密操作。 以下是使用示例: ```java public static void main(String[] args) throws Exception { String key = "mysecretkey"; File inputFile = new File("test.jar"); File encryptedFile = new File("test_encrypted.jar"); File decryptedFile = new File("test_decrypted.jar"); JarEncryptor.encrypt(key, inputFile, encryptedFile); JarEncryptor.decrypt(key, encryptedFile, decryptedFile); } ``` 在上面的示例中,我们使用“mysecretkey”作为密钥对“test.jar”进行加密,然后再对加密后的文件进行解密,最终得到的文件名为“test_decrypted.jar”。 需要注意的是,加密和解密过程中需要使用相同的密钥,否则无法正确解密。同时,密钥应该足够复杂和安全,以保证加密后的文件不会被破解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

01传说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值