2团
Published on 2024-08-16 / 24 Visits
0
0

MyBatis-Plus字段加密存储解决方案

1. 需求背景

项目采用MyBatis-Plus作为ORM工具,近期需要对手机号,账户等敏感信息进行加密存储。

考虑到MyBatis提供了BaseTypeHandler,可以继承此对字段进行自定义操作,于是创建以下解决方案

2. 加解密Handler

因为加密的字段,在部分场景下还需要提取出来执行业务操作,因此此处选用AES对称加密解决方案。

此处,AesEncryptHandler 继承BaseTypeHandler,对数据库中的varchar字段进行加解密操作,具体代码如下所示:

@Slf4j
@MappedTypes({String.class})
@MappedJdbcTypes(JdbcType.VARCHAR)
public class AesEncryptHandler extends BaseTypeHandler<String> {

    private static final byte[] KEY = "zluzuagohu1b9kyayluzuagohu913kyz".getBytes(StandardCharsets.UTF_8);

    private static final byte[] IV = "arbqu12x9ixx0fej".getBytes(StandardCharsets.UTF_8);

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        AES aes = new AES("CBC", "PKCS5Padding", KEY, IV);
        ps.setString(i, aes.encryptBase64(parameter, StandardCharsets.UTF_8));
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        var res = rs.getString(columnName);
        if (CharSequenceUtil.isEmpty(res)) {
            return res;
        }
        AES aes = new AES("CBC", "PKCS5Padding", KEY, IV);
        return aes.decryptStr(res, StandardCharsets.UTF_8);
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        var res = rs.getString(columnIndex);
        if (CharSequenceUtil.isEmpty(res)) {
            return res;
        }
        AES aes = new AES("CBC", "PKCS5Padding", KEY, IV);
        return aes.decryptStr(res, StandardCharsets.UTF_8);
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        var res = cs.getString(columnIndex);
        if (CharSequenceUtil.isEmpty(res)) {
            return res;
        }
        AES aes = new AES("CBC", "PKCS5Padding", KEY, IV);
        return aes.decryptStr(res, StandardCharsets.UTF_8);
    }
}

3. 加密字段配置

@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@TableName(autoResultMap = true)
public class SysUser extends BaseEntity {

    @TableField("`name`")
    private String name;

    @TableField(typeHandler = AesEncryptHandler.class)
    private String phone;
}

参考上文代码示例,需要在实体类上添加@TableName(autoResultMap = true),以及在需要加解密的字段上添加@TableField(typeHandler = AesEncryptHandler.class)注解。

4. 项目配置文件

项目配置文件中,需要添加type-handlers-package配置项,以便MyBatis-Plus注入加解密Handler。

具体如下所示:

mybatis-plus:
  global-config:
    db-config:
      logic-delete-value: 1
      logic-not-delete-value: 0
      logic-delete-field: deleted
      id-type: auto
  configuration:
    map-underscore-to-camel-case: true
  mapper-locations: classpath*:mapper/*.xml
  type-aliases-package: com.doudou.cm.entity
  type-handlers-package: com.doudou.cm.handler


Comment