JAVA返回前端密文(保护加密信息)
1.开启加密类
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface EnableSensitive { String type() default "default"; }
2.加密字段
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface SensitiveEncrypt { String type() default "default"; }
3.加密工具类
import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.util.Base64; public class EncryptionUtils { // 长度必须为16字节(128位),也可用24、32字节(192、256位) private static final String SECRET_KEY = "狗头"; // 可配置化 private static final String ALGORITHM = "AES"; // 加密 public static String encrypt(String plainText) { try { SecretKeySpec keySpec = new SecretKeySpec(SECRET_KEY.getBytes(), ALGORITHM); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, keySpec); byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(encrypted); } catch (Exception e) { throw new RuntimeException("加密失败", e); } } // 解密 public static String decrypt(String cipherText) { try { SecretKeySpec keySpec = new SecretKeySpec(SECRET_KEY.getBytes(), ALGORITHM); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, keySpec); byte[] decodedBytes = Base64.getDecoder().decode(cipherText); byte[] decrypted = cipher.doFinal(decodedBytes); return new String(decrypted, StandardCharsets.UTF_8); } catch (Exception e) { throw new RuntimeException("解密失败", e); } } }
4.RequestBody的解析器Spring
import com.vt.api.jcc_server.annotation.EnableSensitive; import com.vt.api.jcc_server.annotation.SensitiveEncrypt; import com.vt.api.jcc_server.util.EncryptionUtils; import org.springframework.core.MethodParameter; import org.springframework.http.HttpInputMessage; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Type; @RestControllerAdvice public class DecryptRequestBodyAdvice implements RequestBodyAdvice { @Override public boolean supports(MethodParameter methodParameter, Type targetType, Class> converterType) { return true; } @Override public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) { return body; } @Override public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) throws IOException { // 可在这里对原始 JSON 解密 return inputMessage; } @Override public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) { decryptFields(body); return body; } private void decryptFields(Object obj) { if (obj == null) return; if (obj.getClass().getAnnotation(EnableSensitive.class) == null) return; try { for (Field field : obj.getClass().getDeclaredFields()) { if (field.isAnnotationPresent(SensitiveEncrypt.class)) { field.setAccessible(true); String encrypted = (String) field.get(obj); if (encrypted != null) { field.set(obj, EncryptionUtils.decrypt(encrypted)); } } } } catch (Exception e) { e.printStackTrace(); } } }
5.返回时的解析器Spring
import com.baomidou.mybatisplus.core.metadata.IPage; import com.vt.api.jcc_server.annotation.EnableSensitive; import com.vt.api.jcc_server.annotation.SensitiveEncrypt; import com.vt.api.jcc_server.util.EncryptionUtils; import com.vt.framework.common.vo.Result; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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; import java.lang.reflect.Field; import java.util.Collection; @RestControllerAdvice public class EncryptResponseAdvice implements ResponseBodyAdvice { private static final Logger log = LoggerFactory.getLogger(EncryptResponseAdvice.class); @Override public boolean supports(MethodParameter returnType, Class> converterType) { return true; // 也可以加条件过滤 } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { if (body instanceof Result) { Object data = ((Result) body).getResult(); // 空 or 基础类型直接返回,不处理 if (data == null || isPrimitiveOrWrapper(data.getClass())) { return body; } // 分页处理 if (data instanceof IPage) { IPage page = (IPage) data; for (Object record : page.getRecords()) { encryptFields(record); } } // 集合处理(可能是 List) else if (data instanceof Collection) { for (Object item : (Collection) data) { encryptFields(item); } } // 单个实体处理 else { encryptFields(data); } } else { // 防止误处理基础类型返回 if (!isPrimitiveOrWrapper(body.getClass())) { encryptFields(body); } } return body; } private void encryptFields(Object obj) { if (obj == null) return; if (obj.getClass().getAnnotation(EnableSensitive.class) == null) return; Class clazz = obj.getClass(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); try { Object value = field.get(obj); if (value == null) continue; if (field.isAnnotationPresent(SensitiveEncrypt.class) && value instanceof String) { String encrypted = EncryptionUtils.encrypt((String) value); field.set(obj, encrypted); } // 递归处理嵌套对象,比如对象里面还有对象 if (!isPrimitiveOrWrapper(value.getClass())) { encryptFields(value); } } catch (Exception e) { e.printStackTrace(); } } } private boolean isPrimitiveOrWrapper(Class clazz) { return clazz.isPrimitive() || clazz == String.class || Number.class.isAssignableFrom(clazz) || clazz == Boolean.class || clazz == Character.class; } }
6.用法
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import com.vt.api.jcc_server.annotation.EnableSensitive; import com.vt.api.jcc_server.annotation.SensitiveEncrypt; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import java.time.LocalDateTime; /** * 特殊日期管理 * @TableName t_special_date_lib */ @EqualsAndHashCode(callSuper = true) @TableName(value ="t_account_investigated") @Data @Schema(description = "待调查人员账号") @EnableSensitive public class AccountInvestigated { @Schema(description = "姓名") @SensitiveEncrypt private String name; @Schema(description = "银行卡号") @SensitiveEncrypt private String cardNumber; @Schema(description = "银行类型") @SensitiveEncrypt private String type; @Schema(description = "备注") @SensitiveEncrypt private String remark; @Schema(description = "案件id") private String caseId; @TableField(exist = false) private static final long serialVersionUID = 1L; }
(图片来源网络,侵删)
(图片来源网络,侵删)
(图片来源网络,侵删)
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。