Mybatis plus 多字段如何加密不同密码?

User对象

public class User {

    @TableField(typeHandler = EncryptTypeHandler.class)
    private String password;
    
    @TableField(typeHandler = EncryptTypeHandler.class)
    private String mobile;
}

加密方法

public class EncryptTypeHandler extends BaseTypeHandler<String> {
    private static AES aes;
}

项目中加密字段比较多,如上User对象密码和手机号的加密密钥不一样
希望一个密钥对应一个AES,不想频繁的创建AES对象,如何封装这个逻辑

阅读 675
avatarAI BotBETA

对于这个问题,你可以使用一个 Map 数据结构来存储每个字段对应的加密密钥。这样,你就可以为每个字段创建一个单独的 AES 实例,而不是为整个项目创建一个。

以下是一个可能的实现:

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

@MappedTypes(String.class)
public class EncryptTypeHandler extends BaseTypeHandler<String> {
    private static final String AES = "AES";
    private static final String SECRET_KEY = "mySecretKey"; // 默认的密钥,你可以根据需要更改
    private static final String CIPHER_MODE = "AES/ECB/PKCS5Padding"; // 默认的加密模式,你可以根据需要更改
    private static final Map<String, Cipher> CIPHERS = new HashMap<>(); // 存储每个字段对应的加密实例

    static {
        // 初始化所有的 Cipher 实例
        initCiphers();
    }

    private static void initCiphers() {
        // 这里你可以根据需要添加更多的字段和对应的密钥
        String[] fields = {"password", "mobile"}; // 你可以根据需要添加更多的字段
        String[] keys = {"passwordKey", "mobileKey"}; // 你可以根据需要添加更多的密钥
        for (int i = 0; i < fields.length; i++) {
            try {
                Cipher cipher = Cipher.getInstance(CIPHER_MODE);
                SecretKeySpec key = new SecretKeySpec(keys[i].getBytes(), AES);
                cipher.init(Cipher.ENCRYPT_MODE, key);
                CIPHERS.put(fields[i], cipher);
            } catch (Exception e) {
                throw new RuntimeException("Failed to initialize cipher for field " + fields[i], e);
            }
        }
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, encrypt(parameter, CIPHERS.get(parameter))); // 使用对应字段的 Cipher 进行加密
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return decrypt(rs.getString(columnName), CIPHERS.get(columnName)); // 使用对应字段的 Cipher 进行解密
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return decrypt(rs.getString(columnIndex), CIPHERS.get(columnIndex)); // 使用对应字段的 Cipher 进行解密
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return decrypt(cs.getString(columnIndex), CIPHERS.get(columnIndex)); // 使用对应字段的 Cipher 进行解密
    }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题