数据脱敏处理

什么是脱敏

数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。简单来说就是你有些数据并不想让别人看见,需要进行处理再显示在页面上。

项目中如何脱敏数据

一般我们得到的数据基本上是从数据库中获得的,例如存在数据库中的手机号,不能泄露信息,就需要进行脱敏,那我们查出来的时候就要调用脱敏数据的方法,从而达到我们的目的。

public class DataConcealUtil {
    private static final int SIZE = 6;
    private static final String SYMBOL = "*";

    public static String toConceal(String value) {
        if (null == value || "".equals(value)) {
            return value;
        }
        int len = value.length();
        int pamaone = len / 2;
        int pamatwo = pamaone - 1;
        int pamathree = len % 2;
        StringBuilder stringBuilder = new StringBuilder();
        if (len <= 2) {
            if (pamathree == 1) {
                return SYMBOL;
            }
            stringBuilder.append(SYMBOL);
            stringBuilder.append(value.charAt(len - 1));
        } else {
            if (pamatwo <= 0) {
                stringBuilder.append(value.substring(0, 1));
                stringBuilder.append(SYMBOL);
                stringBuilder.append(value.substring(len - 1, len));

            } else if (pamatwo >= SIZE / 2 && SIZE + 1 != len) {
                int pamafive = (len - SIZE) / 2;
                stringBuilder.append(value.substring(0, pamafive));
                for (int i = 0; i < SIZE; i++) {
                    stringBuilder.append(SYMBOL);
                }
                if ((pamathree == 0 && SIZE / 2 == 0) || (pamathree != 0 && SIZE % 2 != 0)) {
                    stringBuilder.append(value.substring(len - pamafive, len));
                } else {
                    stringBuilder.append(value.substring(len - (pamafive + 1), len));
                }
            } else {
                int pamafour = len - 2;
                stringBuilder.append(value.substring(0, 1));
                for (int i = 0; i < pamafour; i++) {
                    stringBuilder.append(SYMBOL);
                }
                stringBuilder.append(value.substring(len - 1, len));
            }
        }
        return stringBuilder.toString();
    }  

转载至:(https://blog.csdn.net/f1576813783/article/details/77253233
在数据库中建表,意图是存放哪些需要脱敏的页面以及相关脱敏的字段

建表图

其中每个页面对应一个view_code(这个说法不准确,后面纠正),上面的name 和code就是对应查询封装的时候的字段名称(如果是Object对象,就保持和原数据库中表字段一致)
之后就是看sql查询得到需要脱敏的数据。

Map<String, Object> modelMap = new HashMap<String, Object>();
        List<Object> list =this.queryByPage(sql, new RowMapper<Object>(){
            @Override
            public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
                Map<String,Object> row = new HashMap<String,Object>();  
                 ResultSetMetaData rowdata =rs.getMetaData();
                 for(int i = 1 ; i<= rowdata.getColumnCount() ; i++){
                     String columnName = rowdata.getColumnLabel(i); 
                     row.put(columnName, rs.getObject(i)==null?"":rs.getObject(i));
                 }
                 if(caltype==TimeLenUtil.TIME_LEN_WORK){
                     long timelen = TimeLenUtil.getWorkTimeLen( String.valueOf(row.get("ACCEPT_TIME")), String.valueOf(row.get("END_TIME")), Long.parseLong(String.valueOf(row.get("PROVINCE"))));//换算工单历时
                     row.put("TIMELONGS",timelen);//工单历时
                     long timelimits = Long.parseLong(String.valueOf(row.get("TIME_LIMIT")))*60;//工单时限秒值
                     row.put("CHAOSHIFLAG",timelen>timelimits?1:0);//是否超时
                     row.put("YUJINGFLAG",(timelen<timelimits&&timelen>timelimits-7200)?1:0);//是否预警
                 }
                 //row.put("TIMELONGS",TimeLenUtil.getTimeLen( String.valueOf(row.get("ACCEPT_TIME"), String.valueOf(row.get("END_TIME"), Long.parseLong(String.valueOf(row.get("PROVINCE"))));//换算工单历时
                return row;
            }
        },pageObj,paralist.toArray());
        List<Object>list2=new ArrayList<Object>();
        list2=DataConcealService.getDataConcealForList(list, "ASSIGNXIU");
        modelMap.put("pageObj", pageObj);
        modelMap.put("list", list2);
        modelMap.put("queryCond", queryCond);
        return modelMap;

上面代码可以看出,查出的数据封装在list<Object>集合里 ,然后调用getDataConcealForList方法。由于我们每次查询得到的数据不一定是个list集合,也有可能是个类对象,那么,针对这样的可能性,在DataConcealService.java里面封装了两种方法:

public class DataConcealService implements InitializingBean{
@Autowired
    DataConcealDao dataConcealDao;
    public static String WFM_DATA_SWITCH = ConfigTypeUtil.getValue("WFM_DATA_SWITCH");//配置文件中读取到脱敏开关
    static Map<String,List<String>> dataConcealMap=new HashMap<String, List<String>>();//存放脱敏的字段
    /**
     * 初始化脱敏字段的配置
     */
    @Override
    public  void afterPropertiesSet() throws Exception {
        if("ON".equals(WFM_DATA_SWITCH)){
            List<DataConceal> dataConcealist=dataConcealDao.getDataConceal();
            for(DataConceal dc:dataConcealist){
                List<String> dcList=dataConcealMap.get(dc.getViewCode());
                if(dcList==null){
                    dcList=new ArrayList<String>();
                }
                dcList.add(dc.getCode());
                dataConcealMap.put(dc.getViewCode(), dcList);
            }
        }
        
    }
/**
     * 根据数据库字段的配置,将横表的内容进行脱敏
     * @param obj 将实体类的内容进行脱敏
     * @param viewCode
     * @return
     */
    @SuppressWarnings("unchecked")
    public static List<Object> getDataConcealForList(List <Object> objList,String viewCode) {
        List <Object> list =new ArrayList <Object>();
        if("ON".equals(WFM_DATA_SWITCH)){
            try {
                List<String> dataConcealist=dataConcealMap.get(viewCode);
                if(dataConcealist!=null && dataConcealist.size()>0){
                 for(int i = 0;i<objList.size();i++){
                    Object obj = objList.get(i);
                    String json=JacksonUtil.obj2json(obj);
                    JSONObject jsonObj=JSONObject.fromObject(json);
                    for(String dataCode:dataConcealist){
                        if(CommonUtil.hasValue(jsonObj.getString(dataCode)) && !jsonObj.getString(dataCode).equals("null")){
                            String val=DataConcealUtil.toConceal(jsonObj.getString(dataCode));
                            jsonObj.element(dataCode, val);
                        }
                    }
                    list.add((Object) JacksonUtil.json2pojo(jsonObj.toString(),obj.getClass()));
                 }
                    //return list;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return list;
        }else{
        return objList;
        }
    }  
/**
     * 根据数据库字段的配置,将横表的内容进行脱敏
     * @param obj 将实体类的内容进行脱敏
     * @param viewCode
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T getDataConceal(Object obj,String viewCode) {
        if("ON".equals(WFM_DATA_SWITCH)){
            try {
                List<String> dataConcealist=dataConcealMap.get(viewCode);
                System.out.println(dataConcealMap.get(viewCode));
                if(dataConcealist!=null && dataConcealist.size()>0){
                    String json=JacksonUtil.obj2json(obj);
                    System.out.println(json);
                    JSONObject jsonObj=JSONObject.fromObject(json);
                    System.out.println(jsonObj);
                    for(String dataCode:dataConcealist){
                        System.out.println(jsonObj.getString(dataCode));
                        if(CommonUtil.hasValue(jsonObj.getString(dataCode)) && !jsonObj.getString(dataCode).equals("null")){
                            String val=DataConcealUtil.toConceal(jsonObj.getString(dataCode));
                            jsonObj.element(dataCode, val);
                        }
                    }
                //  System.out.println(JacksonUtil.json2pojo(jsonObj.toString(),obj.getClass()));
                    return (T) JacksonUtil.json2pojo(jsonObj.toString(),obj.getClass());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return (T) obj;
        }else{
            return (T) obj;
        }
    }
}

执行流程就是这样啦,前面提到一个不正确的理论是一个页面对应一个view_code,不准确的原因是因为一个页面可能执行多条查询sql 语句。这样的话,共用一个view_code就会导致其他的sql不能正确执行,因此我的理解是一条查询sql对应一个view_code,页面编码不一样,view_name是可以一样的,所以就能保证各个数据进行脱敏互不干扰。效果如下图:

效果图

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容