diff --git a/src/main/java/com/spring/common/typehandler/EncryptTypeHandler.java b/src/main/java/com/spring/common/typehandler/EncryptTypeHandler.java new file mode 100644 index 00000000..cb7780aa --- /dev/null +++ b/src/main/java/com/spring/common/typehandler/EncryptTypeHandler.java @@ -0,0 +1,39 @@ +package com.spring.common.typehandler; + +import com.spring.common.utils.AesUtils; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedTypes; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * MyBatis TypeHandler:在 SQL 层面自动加解密字符串字段。 + * 写入数据库时加密,读取时解密,Java 层始终操作明文。 + */ +@MappedTypes(String.class) +public class EncryptTypeHandler extends BaseTypeHandler { + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { + ps.setString(i, AesUtils.encrypt(parameter)); + } + + @Override + public String getNullableResult(ResultSet rs, String columnName) throws SQLException { + return AesUtils.decrypt(rs.getString(columnName)); + } + + @Override + public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + return AesUtils.decrypt(rs.getString(columnIndex)); + } + + @Override + public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { + return AesUtils.decrypt(cs.getString(columnIndex)); + } +} diff --git a/src/main/java/com/spring/common/utils/AesUtils.java b/src/main/java/com/spring/common/utils/AesUtils.java new file mode 100644 index 00000000..a62d29ce --- /dev/null +++ b/src/main/java/com/spring/common/utils/AesUtils.java @@ -0,0 +1,66 @@ +package com.spring.common.utils; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +/** + * AES对称加密工具类,用于IFS密码等需要可逆加密的场景。 + * 已加密的值以 "ENC:" 前缀标识,保持对旧明文数据的向下兼容。 + */ +public class AesUtils { + + /** 16字节 = 128位 AES密钥,生产环境建议通过配置文件注入 */ + private static final String AES_KEY = "PLMIfsKey@202501"; + private static final String ALGORITHM = "AES/ECB/PKCS5Padding"; + private static final String ENC_PREFIX = "ENC:"; + + /** + * 加密明文,返回带 ENC: 前缀的密文字符串 + */ + public static String encrypt(String plaintext) { + if (plaintext == null || plaintext.isEmpty()) { + return plaintext; + } + if (plaintext.startsWith(ENC_PREFIX)) { + return plaintext; + } + try { + SecretKeySpec keySpec = new SecretKeySpec(AES_KEY.getBytes(StandardCharsets.UTF_8), "AES"); + Cipher cipher = Cipher.getInstance(ALGORITHM); + cipher.init(Cipher.ENCRYPT_MODE, keySpec); + byte[] encrypted = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8)); + return ENC_PREFIX + Base64.getEncoder().encodeToString(encrypted); + } catch (Exception e) { + throw new RuntimeException("AES加密失败", e); + } + } + + /** + * 解密带 ENC: 前缀的密文,返回明文。 + * 若值不含前缀(旧明文数据),直接原样返回,保持向下兼容。 + */ + public static String decrypt(String ciphertext) { + if (ciphertext == null || ciphertext.isEmpty()) { + return ciphertext; + } + if (!ciphertext.startsWith(ENC_PREFIX)) { + return ciphertext; + } + try { + String base64 = ciphertext.substring(ENC_PREFIX.length()); + SecretKeySpec keySpec = new SecretKeySpec(AES_KEY.getBytes(StandardCharsets.UTF_8), "AES"); + Cipher cipher = Cipher.getInstance(ALGORITHM); + cipher.init(Cipher.DECRYPT_MODE, keySpec); + byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(base64)); + return new String(decrypted, StandardCharsets.UTF_8); + } catch (Exception e) { + throw new RuntimeException("AES解密失败", e); + } + } + + public static boolean isEncrypted(String value) { + return value != null && value.startsWith(ENC_PREFIX); + } +} diff --git a/src/main/java/com/spring/modules/sys/entity/SysUserEntity.java b/src/main/java/com/spring/modules/sys/entity/SysUserEntity.java index 06588b48..1fe373fe 100644 --- a/src/main/java/com/spring/modules/sys/entity/SysUserEntity.java +++ b/src/main/java/com/spring/modules/sys/entity/SysUserEntity.java @@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; +import com.spring.common.typehandler.EncryptTypeHandler; import com.spring.common.utils.QueryPage; import com.spring.common.validator.group.AddGroup; import com.spring.common.validator.group.UpdateGroup; @@ -23,7 +24,7 @@ import java.util.List; * * */ -@TableName("sys_user") +@TableName(value = "sys_user", autoResultMap = true) public class SysUserEntity extends QueryPage implements Serializable { private static final long serialVersionUID = 1L; @@ -100,6 +101,7 @@ public class SysUserEntity extends QueryPage implements Serializable { private String ifsUsername; + @TableField(value = "ifs_password", typeHandler = EncryptTypeHandler.class) private String ifsPassword; /** diff --git a/src/main/java/com/spring/modules/sys/service/impl/SysUserServiceImpl.java b/src/main/java/com/spring/modules/sys/service/impl/SysUserServiceImpl.java index a43ff440..3f9d6ada 100644 --- a/src/main/java/com/spring/modules/sys/service/impl/SysUserServiceImpl.java +++ b/src/main/java/com/spring/modules/sys/service/impl/SysUserServiceImpl.java @@ -1,4 +1,4 @@ - + package com.spring.modules.sys.service.impl; @@ -100,7 +100,7 @@ public class SysUserServiceImpl extends ServiceImpl i user.setPassword(new Sha256Hash(user.getPassword(), salt).toHex()); user.setSalt(salt); this.save(user); - + //检查角色是否越权 //checkRole(user); //添加工厂权限 @@ -134,10 +134,10 @@ public class SysUserServiceImpl extends ServiceImpl i user.setPassword(new Sha256Hash(user.getPassword(), user.getSalt()).toHex()); } this.updateById(user); - + //检查角色是否越权 //checkRole(user); - + //保存用户与角色关系 sysUserRoleService.saveOrUpdate(user.getUserId(), user.getRoleIdList()); userJobService.updateUserJobInfo(user); @@ -188,7 +188,7 @@ public class SysUserServiceImpl extends ServiceImpl i return this.update(userEntity, new QueryWrapper().eq("user_id", userId)); } - + /** * 检查角色是否越权 */ @@ -200,7 +200,7 @@ public class SysUserServiceImpl extends ServiceImpl i if(user.getCreateUserId() == Constant.SUPER_ADMIN || sysMenuDao.checkSuperAdmin(((SysUserEntity) SecurityUtils.getSubject().getPrincipal()).getUserId()).size()>0){ return ; } - + //查询用户创建的角色列表 List roleIdList = sysRoleService.queryRoleIdList(user.getCreateUserId()); @@ -236,4 +236,4 @@ public class SysUserServiceImpl extends ServiceImpl i return baseMapper.queryByDomainControlAccount(username); } -} \ No newline at end of file +}