当前位置: 首页 > news >正文

企业建站服务热线百度seo2022

企业建站服务热线,百度seo2022,您提交的网站域名无备案,做舞台灯光的在哪些网站接订单呢1 背景 需求是某些接口返回的信息,涉及到敏感数据的必须进行脱敏操作 2 思路 ①要做成可配置多策略的脱敏操作,要不然一个个接口进行脱敏操作,重复的工作量太多,很显然违背了“多写一行算我输”的程序员规范。思来想去&#xff…

1 背景

需求是某些接口返回的信息,涉及到敏感数据的必须进行脱敏操作
2 思路

①要做成可配置多策略的脱敏操作,要不然一个个接口进行脱敏操作,重复的工作量太多,很显然违背了“多写一行算我输”的程序员规范。思来想去,定义数据脱敏注解和数据脱敏逻辑的接口, 在返回类上,对需要进行脱敏的属性加上,并指定对应的脱敏策略操作。

②接下来我只需要拦截控制器返回的数据,找到带有脱敏注解的属性操作即可,一开始打算用 @ControllerAdvice 去实现,但发现需要自己去反射类获取注解。当返回对象比较复杂,需要递归去反射,性能一下子就会降低,于是换种思路,我想到平时使用的 @JsonFormat,跟我现在的场景很类似,通过自定义注解跟字段解析器,对字段进行自定义解析,tql。
3 实现代码
3.1自定义数据注解,并可以配置数据脱敏策略:

package com.wkf.workrecord.tools.desensitization;
     
    import java.lang.annotation.*;
     
    /**
     * 注解类
     * @author wuKeFan
     * @date 2023-02-20 09:36:39
     */
     
    @Target({ElementType.FIELD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface DataMasking {
     
        DataMaskingFunc maskFunc() default DataMaskingFunc.NO_MASK;
     
    }

3.2 自定义 Serializer,参考 jackson 的 StringSerializer,下面的示例只针对 String 类型进行脱敏

DataMaskingOperation.class:

package com.wkf.workrecord.tools.desensitization;
     
    /**
     * 接口脱敏操作接口类
     * @author wuKeFan
     * @date 2023-02-20 09:37:48
     */
    public interface DataMaskingOperation {
     
        String MASK_CHAR = “*”;
     
        String mask(String content, String maskChar);
     
    }

DataMaskingFunc.class:

package com.wkf.workrecord.tools.desensitization;
     
    import org.springframework.util.StringUtils;
     
    /**
     * 脱敏转换操作枚举类
     * @author wuKeFan
     * @date 2023-02-20 09:38:35
     */
    public enum DataMaskingFunc {
     
        /**
         *  脱敏转换器
         */
        NO_MASK((str, maskChar) -> {
            return str;
        }),
        ALL_MASK((str, maskChar) -> {
            if (StringUtils.hasLength(str)) {
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < str.length(); i++) {
                    sb.append(StringUtils.hasLength(maskChar) ? maskChar : DataMaskingOperation.MASK_CHAR);
                }
                return sb.toString();
            } else {
                return str;
            }
        });
     
        private final DataMaskingOperation operation;
     
        private DataMaskingFunc(DataMaskingOperation operation) {
            this.operation = operation;
        }
     
        public DataMaskingOperation operation() {
            return this.operation;
        }
     
    }

DataMaskingSerializer.class:

package com.wkf.workrecord.tools.desensitization;
     
    import com.fasterxml.jackson.core.JsonGenerator;
    import com.fasterxml.jackson.databind.JavaType;
    import com.fasterxml.jackson.databind.JsonMappingException;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.SerializerProvider;
    import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
    import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
    import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
     
    import java.io.IOException;
    import java.util.Objects;
     
    /**
     * 自定义Serializer
     * @author wuKeFan
     * @date 2023-02-20 09:39:47
     */
    public final class DataMaskingSerializer extends StdScalarSerializer {
        private final DataMaskingOperation operation;
     
        public DataMaskingSerializer() {
            super(String.class, false);
            this.operation = null;
        }
     
        public DataMaskingSerializer(DataMaskingOperation operation) {
            super(String.class, false);
            this.operation = operation;
        }
     
     
        public boolean isEmpty(SerializerProvider prov, Object value) {
            String str = (String)value;
            return str.isEmpty();
        }
     
        public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
            if (Objects.isNull(operation)) {
                String content = DataMaskingFunc.ALL_MASK.operation().mask((String) value, null);
                gen.writeString(content);
            } else {
                String content = operation.mask((String) value, null);
                gen.writeString(content);
            }
        }
     
        public final void serializeWithType(Object value, JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer) throws IOException {
            this.serialize(value, gen, provider);
        }
     
        public JsonNode getSchema(SerializerProvider provider) {
            return this.createSchemaNode(“string”, true);
        }
     
        public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException {
            this.visitStringFormat(visitor, typeHint);
        }
    }

3.3 自定义 AnnotationIntrospector,适配我们自定义注解返回相应的 Serializer

package com.wkf.workrecord.tools.desensitization;
     
    import com.fasterxml.jackson.databind.introspect.Annotated;
    import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector;
    import lombok.extern.slf4j.Slf4j;
     
    /**
     * @author wuKeFan
     * @date 2023-02-20 09:43:41
     */
    @Slf4j
    public class DataMaskingAnnotationIntroSpector extends NopAnnotationIntrospector {
     
        @Override
        public Object findSerializer(Annotated am) {
            DataMasking annotation = am.getAnnotation(DataMasking.class);
            if (annotation != null) {
                return new DataMaskingSerializer(annotation.maskFunc().operation());
            }
            return null;
        }
     
    }

3.4 覆盖 ObjectMapper:

package com.wkf.workrecord.tools.desensitization;
     
    import com.fasterxml.jackson.databind.AnnotationIntrospector;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
     
    /**
     * 覆盖 ObjectMapper
     * @author wuKeFan
     * @date 2023-02-20 09:44:35
     */
    @Configuration(proxyBeanMethods = false)
    public class DataMaskConfiguration {
     
        @Configuration(proxyBeanMethods = false)
        @ConditionalOnClass({Jackson2ObjectMapperBuilder.class})
        static class JacksonObjectMapperConfiguration {
            JacksonObjectMapperConfiguration() {
            }
     
            @Bean
            @Primary
            ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
                ObjectMapper objectMapper = builder.createXmlMapper(false).build();
                AnnotationIntrospector ai = objectMapper.getSerializationConfig().getAnnotationIntrospector();
                AnnotationIntrospector newAi = AnnotationIntrospectorPair.pair(ai, new DataMaskingAnnotationIntroSpector());
                objectMapper.setAnnotationIntrospector(newAi);
                return objectMapper;
            }
        }
     
    }

3.5 返回对象加上注解:

package com.wkf.workrecord.tools.desensitization;
     
    import lombok.Data;
     
    import java.io.Serializable;
     
    /**
     * 需要脱敏的实体类
     * @author wuKeFan
     * @date 2023-02-20 09:35:52
     */
    @Data
    public class User implements Serializable {
        /**
         * 主键ID
         */
        private Long id;
     
        /**
         * 姓名
         */
        @DataMasking(maskFunc = DataMaskingFunc.ALL_MASK)
        private String name;
     
        /**
         * 年龄
         */
        private Integer age;
     
        /**
         * 邮箱
         */
        @DataMasking(maskFunc = DataMaskingFunc.ALL_MASK)
        private String email;
     
    }

4 测试

我们写一个Controller测试一下看是不是我们需要的效果
4.1 测试的Controller类DesensitizationController.class如下:

package com.wkf.workrecord.tools.desensitization;
     
    import com.biboheart.brick.model.BhResponseResult;
    import com.wkf.workrecord.utils.ResultVOUtils;
    import lombok.RequiredArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
     
    /**
     * 测试接口脱敏测试控制类
     * @author wuKeFan
     * @date 2022-06-21 17:23
     */
    @Slf4j
    @RestController
    @RequiredArgsConstructor
    @RequestMapping(“/desensitization/”)
    public class DesensitizationController {
     
        @RequestMapping(value = “test”, method = {RequestMethod.GET, RequestMethod.POST})
        public BhResponseResult test() {
            User user = new User();
            user.setAge(1);
            user.setEmail(“123456789@qq.com”);
            user.setName(“吴名氏”);
            user.setId(1L);
            return ResultVOUtils.success(user);
        }
     
    }

4.2 PostMan接口请求,效果符合预期,如图:

————————————————
版权声明:本文为CSDN博主「吴名氏.」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_37284798/article/details/129118284

http://www.ds6.com.cn/news/6144.html

相关文章:

  • win10 做网站服务器百度咨询
  • 杭州app开发公司普悦科技南宁seo网站排名优化公司
  • 重庆观音桥步行街上海建站seo
  • 个人可以网站备案吗网站排名在线优化工具
  • 查竣工验收报告的网站百度竞价查询
  • 做优化很好的网站网站搜索优化
  • 长业建设集团有限公司网站口碑营销方案怎么写
  • 在网站留外链怎么做怎么联系百度客服
  • 回收那个网站做推广好南宁百度seo排名优化软件
  • 网站的网页声明怎么做身边的网络营销案例
  • 轻松筹 做的网站价格好口碑关键词优化地址
  • 昆明网站seo报价搜索引擎优化的内容包括
  • 重庆网站建设快速建站搜索seo怎么优化
  • 一家做特卖的网站叫什么时候商丘网站seo
  • 电子工程师网站廊坊网站排名优化公司哪家好
  • 公司网站建设备选方案评价标准seo优化工具哪个好
  • 文体广电旅游局网站建设方案最近比较火的关键词
  • 建企业网站需要哪些资料二级域名和一级域名优化难度
  • 教育技术学网站模版亚马逊seo什么意思
  • 湖州网站建设哪家公司好西地那非片的功效与作用
  • 网站建设构成qq群推广平台
  • 网站的版式设计泰安百度推广代理商
  • 介绍公司的网站有哪些网络营销方案的范文
  • 可以做网站的渠道怎么开发网站
  • 做网站语言杭州推广公司
  • 福田网站建设公司简述seo的基本步骤
  • 做网站的公司哪家强小广告
  • 视频教学互动网站建设搜索引擎营销优化
  • 网站建设有用吗建站工具有哪些
  • wordpress 如何购买主题百中搜优化软件靠谱吗