敏感数据如何优雅的加密存储到数据库

484 阅读2分钟

springboot项目如何做到优雅数据加密存储。本方案是基于mybatis-plus的,我们来实现手机号用aes加密后存储到数据库举例

第一步

定义自己的 TypeHandler,需要继承ibatis 的 BaseTypeHandler,实现他的get set方法即可。

package com.mrxu.framework.boot.mybatisplus.encrypt;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.mrxu.framework.common.util.MrxuAssert;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

@Component
public class AesEncryptTypeHandler <T> extends BaseTypeHandler<T> {

    @Value("${mybatis-plus.mrxu-encrypt.aesKey:}")
    private String aesKey;

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        MrxuAssert.isNotEmpty(aesKey,"请设置aes加密秘钥:mybatis-plus.mrxu-encrypt.aesKey");
        ps.setString(i, SecureUtil.aes(aesKey.getBytes(StandardCharsets.UTF_8)).encryptBase64((String)parameter));
    }

    @Override
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        MrxuAssert.isNotEmpty(aesKey,"请设置aes加密秘钥:mybatis-plus.mrxu-encrypt.aesKey");
        String columnValue = rs.getString(columnName);
        return StrUtil.isBlank(columnValue) ? (T)columnValue : (T) SecureUtil.aes(aesKey.getBytes(StandardCharsets.UTF_8)).decryptStr(columnValue);
    }

    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        MrxuAssert.isNotEmpty(aesKey,"请设置aes加密秘钥:mybatis-plus.mrxu-encrypt.aesKey");
        String columnValue = rs.getString(columnIndex);
        return StrUtil.isBlank(columnValue) ? (T)columnValue : (T)SecureUtil.aes(aesKey.getBytes(StandardCharsets.UTF_8)).decryptStr(columnValue);
    }

    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        MrxuAssert.isNotEmpty(aesKey,"请设置aes加密秘钥:mybatis-plus.mrxu-encrypt.aesKey");
        String columnValue = cs.getString(columnIndex);
        return StrUtil.isBlank(columnValue) ? (T)columnValue : (T)SecureUtil.aes(aesKey.getBytes(StandardCharsets.UTF_8)).decryptStr(columnValue);
    }

}

1 setNonNullParameter:会在我们向数据库插入或更新数据时调用,我们在这里重新设置我们要更新或插入字段的值用aes加密即可。

2 get方法:在查询时候调用,查询时候我们需要对数据库存储的数据进行aes解密。

3 Component注解:把当前自定义的加密TypeHandler装载到spring容器中 主要是想把aes加密的秘钥通过配置文件获取,如果不需要从陪配置文件获取可以不用装载到spring容器中。

第二步

 在我们需要加密字段上加 TableField注解 参数 typeHandler传入我们刚自定义TypeHandler的class即可。

@TableField(value = "mobile",typeHandler = AesEncryptTypeHandler.class)
private String mobile;

这里还需要把我们数据库表对应实体类的TableName注解参数autoResultMap设置成true。

@TableName(value = "member_base",autoResultMap = true)
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel("会员")
public class MemberBase {}

完成上面两步即可

同理如果我们需要md5 或者 base64 加密,按照上面步骤也很容易实现,需要说明的是如果你的sql在xml中定义的还需要做额外的处理