通过mybatis自定义参数类型转换器,进行数据库字段加密脱敏

3552 篇文章 114 订阅

1 问题背景

在数据库存储人员的信息时,有一些信息是敏感数据,如身份证号、出生地等。为了防止信息泄漏,这些信息不允许直接在数据库中查看,此时就需要对这些字段进行加密存储,但在页面查看的仍旧是解密后的数据。这里就涉及到加解密的问题,有两种解决方案。

2 解决方案

2.1 使用数据库加密算法

通过数据库自带的加密算法,在sql里直接使用算法加解密,这种有较多缺点,不推荐使用。

  • 写法繁琐,不易开发维护

  • 适配多种数据库时,算法难以统一,工作量也剧增

2.2 使用mybatis的自定义参数类型转换器

    通过自定义Java类型和类型转换器,并在mapper.xml里标注类型,通过mybatis进行加解密。

  • 加密算法可自由选择

  • 开发维护比较简单方便

  • 不存在适配多种数据库的问题

3 一般web项目使用

3.1 创建自定义Java类型

创建一个空白类,在mapper.xml文件查询和新增修改时标注说明,表示需要mybatis进行相关类型转换。

@Alias("SecretField")
public class SecretField {
}
复制代码

3.2 自定义类的转换处理器

这里使用国密SM4进行加解密,当然算法可自由选择别的如AES等。

@MappedTypes注解映射刚才的自定义Java类

@MappedTypes(SecretField.class)
public class SecretFieldTypeHandler extends BaseTypeHandler<String> {

    private static final Logger log = LoggerFactory.getLogger(SecretFieldTypeHandler.class);

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        try {
            if (StringUtils.hasText(parameter)) {
                String encryptStr = Sm4Util.encryptData_ECB(parameter);
                ps.setString(i, encryptStr);
            }
        } catch (Exception e) {
            ps.setString(i, parameter);
            log.error("mybatis加密参数异常,i:{},parameter:{}", i, parameter);
        }
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String columnValue = rs.getString(columnName);
        try {
            if (StringUtils.hasText(columnValue)) {
                columnValue = Sm4Util.decryptData_ECB(columnValue);
            }
        } catch (Exception e) {
            log.error("mybatis解密参数异常,columnName:{}, columnValue:{}", columnName, columnValue);
        }
        return columnValue;
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return null;
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return null;
    }
}
复制代码

3.3 配置自定义类型和类型转换器

这一步也可使用相关注解完成。

配置文件为mybatis的配置文件,如mybatis-config.xml。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE configuration PUBLIC "-//mybaties.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
    </settings>

    <typeAliases>
            <typeAlias type="com.banxian.mybatis.alias.SecretField" alias="SecretField"/>
    </typeAliases>
    <typeHandlers>
        <typeHandler handler="com.banxian.mybatis.typehandler.SecretFieldTypeHandler" />
    </typeHandlers>

</configuration>
复制代码

3.4 查询使用

查询返回需通过resultMap映射,在加密字段进行javaType指明需要的类型转换器

另外如果旧代码中结果集大量直接使用map返回,时间紧张的情况下,则可考虑写一个工具类,在service里调用进行手动解密,没得办法呀!。

    <resultMap id="BaseResultMap" type="User">
        <result column="sfz" property="sfz"  javaType="SecretField"/>
    </resultMap>
复制代码

3.5 新增修改使用

在设置相关参数值时,也就是在#{}里,使用javaType指明需要的类型转换器

   insert into ... values(...
    <if test="sfz!= null">
        #{sfz,jdbcType=VARCHAR,javaType=SecretField},
    </if>
   )
复制代码

4. springboot项目使用

  • 自定义类型和类型转换器代码和上面一样,这里不在赘述。

  • 项目使用了mybatis-plus插件。

4.1 配置自定义类型和类型转换器

在项目配置文件里application.yml里加上配置type-handlers-package 和   type-aliases-package:分别指出你的类型转换器所在包名和自定义类所在包名。

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted
      logic-not-delete-value: "0"
      logic-delete-value: "1"
  mapper-locations: "classpath*:/mapper/**/*.xml"
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  type-handlers-package: com.banxian.mybatis.typehandler
  type-aliases-package: com.banxian.mybatis.alias
复制代码

4.2 mybatis-plus的使用

当然上面web项目的查询、新增和修改使用方法这里也是可以正常使用的

1)在实体类上使用注解 @TableName(autoResultMap = true)

2)在加密字段上指明类型@TableField(value = "sfz", typeHandler = SecretFieldTypeHandler.class)

@Data
@TableName(autoResultMap = true)
public class User implements Serializable {

    private static final long serialVersionUID = 4344848828462926573L;

    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private Integer id;

    /**
     * 名称
     */
    private String userName;

    /**
     * 是否删除 1:是  0:否
     */
    @TableLogic
    private String deleted;

    /**
     * 是否有效 1:是  0:否
     */
    private String valid;

    /**
     * 创建时间
     */
    @TableField(value = "create_at", fill = FieldFill.INSERT)
    private LocalDateTime createAt;

    /**
     * 更新时间
     */
    @TableField(value = "update_at", fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateAt;

    @TableField(value = "sfz", typeHandler = SecretFieldTypeHandler.class)
    private String sfz;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要将自定义类型转换为JSON集合,可以按照以下步骤操作: 1. 创建一个MyBatis TypeHandler实现类,实现TypeHandler接口,或者继承BaseTypeHandler类。例如,可以创建一个名为JsonListTypeHandler的类。 2. 在TypeHandler实现类中重写setNonNullParameter方法和getNullableResult方法。setNonNullParameter方法用于将Java对象转换为数据库字段值,getNullableResult方法用于将数据库字段值转换为Java对象。 3. 在setNonNullParameter方法中,可以使用JSON库(如Jackson或GSON)将Java对象转换为JSON字符串,然后将JSON字符串设置到PreparedStatement对象中。 4. 在getNullableResult方法中,可以从ResultSet对象中获取数据库字段值,并使用JSON库将JSON字符串转换为Java对象。 5. 在MyBatis配置文件(如mybatis-config.xml)中注册这个TypeHandler。可以通过typeHandlers标签将TypeHandler实现类与自定义Java类型关联起来。例如,可以添加以下配置: ```xml <typeHandlers> <typeHandler handler="com.example.JsonListTypeHandler" javaType="com.example.CustomTypeList"/> </typeHandlers> ``` 这里的"com.example.JsonListTypeHandler"是TypeHandler实现类的完整类名,"com.example.CustomTypeList"是自定义Java类型的完整类名。 6. 在映射文件中,使用自定义Java类型和对应的数据库字段。例如: ```xml <resultMap id="customTypeListMap" type="com.example.CustomTypeList"> <id property="id" column="id" /> <result property="name" column="name" /> </resultMap> ``` 通过以上步骤,就可以将自定义类型转换为JSON集合了。在查询时,MyBatis将自动应用TypeHandler,将数据库字段值转换为Java对象;在插入或更新时,MyBatis将自动应用TypeHandler,将Java对象转换为数据库字段值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值