mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索

这篇具有很好参考价值的文章主要介绍了mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前提介绍 (开发环境+需求)

1. 开发框架、环境

springboot+mybatis-plus+mysql5.7(oracle应该也是可以的,没有测试,但实现思路是都可以满足,懒得测oracle了,哈哈)

2. 需求介绍(背景)

需求很简单: 就是将数据存储到数据库,并且将敏感数据字段进行加密处理保存(比如:身份证,手机号,银行卡 等等)

需求也很变态:加密的数据要模糊搜素!!

如果需求不需要模糊搜素,直接加密入库就完事了,直接看这篇文章 mybatis-plus进行数据字段加密解密入库 ,就可以了!

3.设计思路

个人 采用 映射表 分词的 方案进行处理的

mysql 创建 加密 模糊搜索字段 ,将字段加密进行分词处理,保存到 搜索映射表

分词这边采用 es 使用的ik分词器,原因就是:自己写一个分词是不可能的了,算法没那么牛逼 !! ,并且ik 分词器可以自定义词语进行分词

然后再使用 用 mybaitis-plus 自带的注解 @TableField(typeHandler = TypeHandler.class)

mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus

写一个 handle 类继承 BaseTypeHandler ,将数据进行加解密

大致思路是这样 !

4. 具体实现

4.1 . 依赖
<!--        ik分词器-->
        <dependency>
            <groupId>com.janeluo</groupId>
            <artifactId>ikanalyzer</artifactId>
            <version>2012_u6</version>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.lucene</groupId>
                    <artifactId>lucene-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.lucene</groupId>
                    <artifactId>lucene-queryparser</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.lucene</groupId>
                    <artifactId>lucene-analyzers-common</artifactId>
                </exclusion>
            </exclusions>

        </dependency>
        
         <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.12</version>
        </dependency>
        
        <!--        AES加密解密需要包-->
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.15</version>
        </dependency>
4.2 继承Mybatis的 BaseTypeHandler类,重写方法
package com.xiarp.encryptstorage.handler;


import com.xiarp.encryptstorage.util.AesUtil;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.*;

/**
 * @author xiarp
 */
public class TypeHandler extends BaseTypeHandler<String> {


    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, AesUtil.encrypt(parameter));
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return AesUtil.decrypt(rs.getString(columnName));
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return AesUtil.decrypt(rs.getString(columnIndex));
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return AesUtil.decrypt(cs.getString(columnIndex));
    }
}



4.3 AES 加密的工具类
package com.xiarp.encryptstorage.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;


/**
 *  aes 加密的工具类
 *  1.存储 加密的秘钥key
 *  2.实现 aes 加密
 *  3.实现aes解密的功能
 * @author xiarp
 */
@Slf4j
public class AesUtil {
    /**
     * 定义 aes 加密的key
     * 密钥  必须是16位, 自定义,
     * 如果不是16位, 则会出现InvalidKeyException: Illegal key size
     * 解决方案有两种:
     * 需要安装Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files(可以在Oracle下载).
     *  .设置设置key的长度为16个字母和数字的字符窜(128 Bit/8=16字符)就不报错了。
     */
    private static final String KEY = "KEYBYACSJAVAZXLL";

    /**
     *  偏移量
     */
    private static final int OFFSET = 16;
    private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
    private static final String ALGORITHM = "AES";

    /**
     * 加密
     * @param content content
     * @return String
     */
    public static String encrypt(String content) {
        return encrypt(content, KEY);
    }

    /**
     * 解密
     *
     * @param content content
     * @return String
     */
    public static String decrypt(String content) {
        return decrypt(content, KEY);
    }

    /**
     * 加密
     *
     * @param content 需要加密的内容
     * @param key     加密密码
     * @return String
     */
    public static String encrypt(String content, String key) {
        try {
            SecretKeySpec skey = new SecretKeySpec(key.getBytes(), ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(key.getBytes(), 0, OFFSET);
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            //定义加密编码
            String charset = "utf-8";
            byte[] byteContent = content.getBytes(charset);
            // 初始化
            cipher.init(Cipher.ENCRYPT_MODE, skey, iv);
            byte[] result = cipher.doFinal(byteContent);
            // 加密
            return new Base64().encodeToString(result);
        } catch (Exception e) {
            log.debug("加密失败:{}",e.getMessage());
        }
        return null;
    }

    /**
     * AES(256)解密
     *
     * @param content 待解密内容
     * @param key     解密密钥
     * @return 解密之后
     */
    public static String decrypt(String content, String key) {
        try {

            SecretKeySpec skey = new SecretKeySpec(key.getBytes(), ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(key.getBytes(), 0, OFFSET);
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            // 初始化
            String charset = "utf-8";
            cipher.init(Cipher.DECRYPT_MODE, skey, iv);
            byte[] result = cipher.doFinal(new Base64().decode(content));
            // 解密
            return new String(result,charset);
        } catch (Exception e) {
            log.debug("解密失败:{}",e.getMessage());
        }
        return null;
    }

}
                                                                        
4.4 分词器 工具类 (部分分词 + ik【可自定义扩展分词】)以及使用介绍
  • 工具类
package com.xiarp.encryptstorage.util;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.StrUtil;

import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * @author xiarp
 */
public class AnalyzerUtil {
    /**
     * ik
     *
     * @param str    str
     * @param length length
     * @return List<String>
     */
    public static List<String> ikSegmentationList(String str, Integer length) {
        List<String> list = new LinkedList<>();
        try {
            if (StrUtil.isEmpty(str)) {
                return ListUtil.empty();
            }
            StringReader stringReader = new StringReader(str);
            IKSegmenter ik = new IKSegmenter(stringReader, false);
            Lexeme le;
            while ((le = ik.next()) != null) {
                String lexemeText = le.getLexemeText();
                if (lexemeText.length() >= length) {
                    list.add(lexemeText);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 部分分词
     *
     * @param str    str
     * @param length length
     * @return List<String>
     */
    public static List<String> partSegmentationList(String str, Integer length) {
        List<String> list = new ArrayList<>();
        if (StrUtil.isEmpty(str)) {
            return ListUtil.empty();
        }
        int strLength = str.length();
        for (int startIndex = 0; startIndex <= strLength - length; startIndex++) {
            String substring = str.substring(startIndex, startIndex + length);
            list.add(substring);
        }
        return list;
    }
}

  • ik 分词器 配置文件+ 自定义扩展分词文件+ 不需要分词文件

文件1: IKAnalyzer.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <comment>IKAnalyzer扩展配置</comment>
    <!--用户的扩展字典 -->
    <entry key="ext_dict">extend.dic</entry>
    <!--用户扩展停止词字典 -->
    <entry key="ext_stopwords">stopword.dic</entry>
</properties>

文件2: extend.dic (扩展词典) ,没有使用是空白的
文件3: stopword.dic (扩展停止词典,不要这些 分词) 没有使用是空白的

文件全部创建在resources 下

mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus

4.4.1 分词器工具类使用解析,测试

ik 分词器 (智能分词)
mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus

mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus
参数1: 需要分词的字符串,
参数2: 结果保留几个字符以上字符串

mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus
这边获取了 字符 >=2 的所有分词数据

扩展词典 :

现在我在 extend.dic (扩展词典) 文件中加上 “暴富的梦” 跟 “今天是星期五” ,看看结果

mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus

再次运行刚才测试代码 ,可以看到分词加进去了
mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus

取消扩展词典:

就是这个词,不要出现,比如分词结果不要 “星期五” 这个词出现

mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus
再次执行
mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus

ik 分词用来分词手机号数字串类型的不太友好 (有处理方法,可以改ik 的工具类,这边就不改了,懒!),因此 可以 简单写了个 第二种方法,不知道叫什么,就叫部分分词了

参数同理

mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus

是按照,从第0位 开始 取三位,然后 从 第1 位开始取三位 。。。。。 以此类推,直到结束

【注意】:这边涉及到一个性能和安全问题,比如分词的字符长度设置的太长,加密又不安全,设置的太短,有影响性能,耗费的存储空间又多,因此,选择合适的分词长度 很重要 (数据量过小不用考虑)

就比如手机号就可以设置成 4 位,为一个分片,模糊搜索也可以说明 “请输入手机号后四位查询”

mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus

4.5 SQL 创建 分词 映射表(word_part_mapping) 以及模拟数据 用户(sys_user) 表

mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus

mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus

使用

对应需要加密实体类加上注解
mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus

简单模拟数据 新增 查询

新增数据 需加密字段分词处理逻辑 (映射表)
mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus
再提一句:不要再循环里添加数据,要批量!!!

**查询 数据 **
mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus

mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus
我向数据库中 添加了五条数据

以加密的形式存在
mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus

查询结果是明文【符合加密存储,明文输出要求
mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus

模糊搜索

输入一个参数,输出三条数据,符合单模糊
mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus

输入多个参数 ,输出符合的两条数据,符合 多模糊

mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus
mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索,mybatis,mybatisplus

修改数据 直接看 这篇文章即可,一样的

注意一点是,修改到了敏感数据,需要先删除原先敏感数据的分词,重新分词进行添加!!,所以前边说的 批量添加分词映射表数据 可以 自己写一个工具类!!

文章有遗漏的工具类,或者有需要的其他信息,可以打在评论区!! 欢迎讨论指正,当然要是有更好的实现 方案,请指教!!!文章来源地址https://www.toymoban.com/news/detail-704176.html

到了这里,关于mybatis-plus 数据字段进行加解密入库,且加密字段支持模糊搜索的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Mybatis-plus怎么更新Null字段?

    本文介绍【Mybatis-plus】updateById()方法不能更新字段为null的原因及解决办法。 在日常项目开发过程中,经常会使用Mybatis-plus的updateById()方法,快速将接收道德参数或者查询结果中原本不为null的字段更新为null,并且该字段在数据库中可为null,这个时候使用updateById()并不能实现

    2024年02月13日
    浏览(51)
  • mybatis-plus 根据指定字段 批量 删除/修改

    mybatis-plus 提供了根据id批量更新和修改的方法,这个大家都不陌生 但是当表没有id的时候怎么办) 这个就不说了,就是因为不想手写SQL 所以才有这篇博客 mybatis plus 的 executeBatch 参考 mybatis plus 的updateBatchById 方法. 调用处: 接口 重写方法 实现 这种写法其实批量的效率还是比较慢的

    2024年02月13日
    浏览(39)
  • mybatis-plus更新字段为null值

    mybatis-plus相信大家都不陌生所以不在介绍 首先我们先看一下mybatis-plus的官网上的介绍  官网推荐的有三种方式可以实现 第一种:调整全局策略, mybatis-plus默认的全局策略为NOT_NULL非空默认策略,其实就是当更新是某个字段为空,则不对该字段进行更新,这也是我们常用的策略所此种

    2024年02月14日
    浏览(54)
  • Mybatis-Plus处理Mysql Json类型字段

    Mysql 5.7.8开始支持Json对象和Json数组,但在Mysql 8版本中使用Json性能更佳。 使用Json格式的好处: 无须预定义字段:字段可以无限拓展,避免了ALTER ADD COLUMN的操作,使用更加灵活。 处理稀疏字段:避免了稀疏字段的NULL值,避免冗余存储。 支持索引:相比于字符串格式的JSON,

    2024年02月03日
    浏览(51)
  • MyBatis-Plus如何将字段修改为空值

    不推荐使用原因:作用范围太广,调用MyBatis-Plus封装的update会不经意将字段改为空 不推荐使用原因:相对于方案一作用范围相对较小,但调用MyBatis-Plus封装的update也会不经意将字段改为空 推荐原因:不影响任何地方只在此处生效

    2024年02月16日
    浏览(52)
  • Mybatis-plus通过其他字段批量更新或新增

    根据某个或者多个非ID字段进行批量更新 示例通过名称与id两个字段更新 引用mybatis-plus根据某个指定字段批量更新数据库 通过其他字段批量更新或新增

    2024年02月12日
    浏览(49)
  • Mybatis ,Mybatis-plus列表多字段排序,包含sql以及warpper

    首先根据咱们返回前端的数据列来规划好排序字段 如下: 这里的字段为返回VO的字段,要转换成数据库字段然后加入到排序中 示例,穿了 surname,cerRank 多字段,然后是倒序 false 首先创建好映射,如下代码,第一个List 为前端字段VO, 第二个List 为数据库字段。Util.handle 是将两个转换

    2024年02月14日
    浏览(39)
  • SpringBoot - MyBatis-Plus - 如何在查询时排除某些字段?

    写在前面 查询时部分字段不想给前端显示,怎么办? (1)使用SELECT方法,排除字段\\\"password\\\" (2)使用SELECT方法,只显示某些字段 (3)使用@TableField(exist = false),排除某些字段 注:表示当前属性不是数据库的字段,但在项目中必须使用,这样的话在新增/查询等使用BEAN时,

    2024年02月12日
    浏览(42)
  • Mybatis-Plus不能更新对象字段为空值问题解决

    问题描述: 在使用Mybatis-Plus调用updateById方法进行数据更新默认情况下是不能更新空值字段的,而在实际开发过程中,往往会遇到需要将字段值更新为空值的情况,该如何解决呢? 原因分析: Mybatis-Plus中字段的更新策略是通过FieldStrategy属性控制的。在实体字段上,如果不通

    2024年02月12日
    浏览(49)
  • Springboot引入mybatis-plus及操作mysql的json字段

    springboot引入mybatis-plus,创建springboot项目省略 pom文件 配置文件 备注信息 springboot使用mybatis和mybatis-plus没有什么区别,需要注意的是配置文件跟配置名:mybatis-plus 使用mybatis-plus的有点在于,在mybatis的基础上记性了一系列的有效封装,节约了开发时间,有这方面兴趣额同学自行

    2024年02月06日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包