马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
反射+Jackson数据动态脱敏
我有两个字段,name和type,我想要在type为1对数据脱敏,而其他情况不脱敏:
在网上看到了很多利用Jackson的,但是并没有根据不同情况脱敏,以下是参考了deepseek的实现:
@CustomSerializer注解
- @Target(ElementType.FIELD) //表示这个注解只能用在字段上
- @Retention(RetentionPolicy.RUNTIME) //注解在运行时保留,可以通过反射读取
- @JacksonAnnotationsInside //表示这是一个Jackson组合注解
- @JsonSerialize(using = DesensitizeSerializer.class)
- public @interface CustomSerializer {
- DesensitizeRuleEnum function();
- String condition() default "";
- }
复制代码 DesensitizeSerializer, 根据 SpEL 表达式判定是否脱敏:
- public class DesensitizeSerializer extends JsonSerializer<String> implements ContextualSerializer {
- /**
- * 脱敏规则
- */
- private DesensitizeRuleEnum rule;
- private String condition; // SpEL 表达式
- private BeanProperty property; // 当前字段属性
- @Override
- public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
- Object currentObject = getCurrentObject(gen); // 获取当前对象
- boolean shouldMask = evaluateCondition(currentObject);
- if (shouldMask) {
- // 条件满足时脱敏
- gen.writeString(rule.function().apply(value));
- } else {
- // 条件不满足时保留原值
- gen.writeString(value);
- }
- }
- @Override
- public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
- //获取对象属性上的自定义注解
- CustomSerializer annotation = property.getAnnotation(CustomSerializer.class);
- if (annotation != null && String.class == property.getType().getRawClass()) {
- DesensitizeSerializer serializer = new DesensitizeSerializer();
- serializer.rule = annotation.function();
- // 注入条件表达式
- serializer.condition = annotation.condition();
- serializer.property = property;
- return serializer;
- }
- return prov.findValueSerializer(property.getType(), property);
- }
- private boolean evaluateCondition(Object target) {
- if (StringUtils.isEmpty(condition)) {
- return true; // 无条件默认脱敏
- }
- try {
- // 创建SpEL解析器
- ExpressionParser parser = new SpelExpressionParser();
- // 设置上下文(target是被序列化的对象)
- EvaluationContext context = new StandardEvaluationContext(target);
- // 执行表达式并返回布尔结果
- return Boolean.TRUE.equals(parser.parseExpression(condition).getValue(context, Boolean.class));
- } catch (Exception e) {
- log.warn("脱敏条件表达式执行失败: {}", condition, e);
- return false; // 表达式错误时不脱敏
- }
- }
- private Object getCurrentObject(JsonGenerator gen) {
- try {
- // 获取序列化器上下文中的输出层(底层为 BeanSerializer)
- Object outputContext = gen.getOutputContext();
- if (outputContext instanceof JsonWriteContext) {
- JsonWriteContext context = (JsonWriteContext) outputContext;
- // 通过反射获取当前对象实例
- Field currentValueField = JsonWriteContext.class.getDeclaredField("_currentValue");
- currentValueField.setAccessible(true);
- return currentValueField.get(context);
- }
- } catch (Exception e) {
- log.warn("无法获取当前对象", e);
- }
- return null;
- }
- }
复制代码 实体类:
- public class Person{
- @CustomSerializer(function = DesensitizeRuleEnum.USERNAME, condition = "type == '1'.toString()")
- @Schema(description = "姓名")
- private String name;
- @Schema(description = "类别,1:xxxx,0:xxxx")
- private String type;
- }
复制代码 实现需求,结果涉及公司生产数据,就不放了
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |