Merge remote-tracking branch 'origin/5.X' into feature/tenant

# Conflicts:
#	script/sql/oracle/oracle_ry_vue_5.X.sql
#	script/sql/postgres/postgres_ry_vue_5.X.sql
#	script/sql/ry_vue_5.X.sql
#	script/sql/sqlserver/sqlserver_ry_vue_5.X.sql
This commit is contained in:
疯狂的狮子li 2023-02-06 09:47:35 +08:00
commit 4fd3029488
39 changed files with 1198 additions and 23 deletions

View File

@ -36,6 +36,7 @@
<alibaba-ttl.version>2.14.2</alibaba-ttl.version> <alibaba-ttl.version>2.14.2</alibaba-ttl.version>
<xxl-job.version>2.3.1</xxl-job.version> <xxl-job.version>2.3.1</xxl-job.version>
<lombok.version>1.18.24</lombok.version> <lombok.version>1.18.24</lombok.version>
<bouncycastle.version>1.72</bouncycastle.version>
<!-- 临时修复 snakeyaml 漏洞 --> <!-- 临时修复 snakeyaml 漏洞 -->
<snakeyaml.version>1.33</snakeyaml.version> <snakeyaml.version>1.33</snakeyaml.version>
@ -286,6 +287,13 @@
<version>${snakeyaml.version}</version> <version>${snakeyaml.version}</version>
</dependency> </dependency>
<!-- 加密包引入 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-system</artifactId> <artifactId>ruoyi-system</artifactId>

View File

@ -180,6 +180,20 @@ mybatis-plus:
# 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件 # 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件
where-strategy: NOT_NULL where-strategy: NOT_NULL
# 数据加密
mybatis-encryptor:
# 是否开启加密
enable: false
# 默认加密算法
algorithm: BASE64
# 编码方式 BASE64/HEX。默认BASE64
encode: BASE64
# 安全秘钥 对称算法的秘钥 如AESSM4
password:
# 公私钥 非对称算法的公私钥 如SM2RSA
publicKey:
privateKey:
# Swagger配置 # Swagger配置
swagger: swagger:
info: info:

View File

@ -30,6 +30,7 @@
<module>ruoyi-common-translation</module> <module>ruoyi-common-translation</module>
<module>ruoyi-common-sensitive</module> <module>ruoyi-common-sensitive</module>
<module>ruoyi-common-json</module> <module>ruoyi-common-json</module>
<module>ruoyi-common-encrypt</module>
</modules> </modules>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>

View File

@ -145,6 +145,13 @@
<version>${revision}</version> <version>${revision}</version>
</dependency> </dependency>
<!-- 数据库加解密模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-encrypt</artifactId>
<version>${revision}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-common-encrypt</artifactId>
<description>
ruoyi-common-encrypt 数据加解密模块
</description>
<dependencies>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-core</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,44 @@
package com.ruoyi.common.encrypt.annotation;
import com.ruoyi.common.encrypt.enumd.AlgorithmType;
import com.ruoyi.common.encrypt.enumd.EncodeType;
import java.lang.annotation.*;
/**
* 字段加密注解
*
* @author 老马
*/
@Documented
@Inherited
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptField {
/**
* 加密算法
*/
AlgorithmType algorithm() default AlgorithmType.DEFAULT;
/**
* 秘钥AESSM4需要
*/
String password() default "";
/**
* 公钥RSASM2需要
*/
String publicKey() default "";
/**
* 公钥RSASM2需要
*/
String privateKey() default "";
/**
* 编码方式对加密算法为BASE64的不起作用
*/
EncodeType encode() default EncodeType.DEFAULT;
}

View File

@ -0,0 +1,39 @@
package com.ruoyi.common.encrypt.config;
import com.ruoyi.common.encrypt.core.EncryptorManager;
import com.ruoyi.common.encrypt.interceptor.MybatisDecryptInterceptor;
import com.ruoyi.common.encrypt.interceptor.MybatisEncryptInterceptor;
import com.ruoyi.common.encrypt.properties.EncryptorProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
/**
* 加解密配置
*
* @author 老马
* @version 4.6.0
*/
@AutoConfiguration
@ConditionalOnProperty(value = "mybatis-encryptor.enable", havingValue = "true")
public class EncryptorAutoConfiguration {
@Autowired
private EncryptorProperties properties;
@Bean
public EncryptorManager encryptorManager() {
return new EncryptorManager();
}
@Bean
public MybatisEncryptInterceptor mybatisEncryptInterceptor(EncryptorManager encryptorManager) {
return new MybatisEncryptInterceptor(encryptorManager, properties);
}
@Bean
public MybatisDecryptInterceptor mybatisDecryptInterceptor(EncryptorManager encryptorManager) {
return new MybatisDecryptInterceptor(encryptorManager, properties);
}
}

View File

@ -0,0 +1,41 @@
package com.ruoyi.common.encrypt.core;
import com.ruoyi.common.encrypt.enumd.AlgorithmType;
import com.ruoyi.common.encrypt.enumd.EncodeType;
import lombok.Data;
/**
* 加密上下文 用于encryptor传递必要的参数
*
* @author 老马
* @version 4.6.0
*/
@Data
public class EncryptContext {
/**
* 默认算法
*/
private AlgorithmType algorithm;
/**
* 安全秘钥
*/
private String password;
/**
* 公钥
*/
private String publicKey;
/**
* 私钥
*/
private String privateKey;
/**
* 编码方式base64/hex
*/
private EncodeType encode;
}

View File

@ -0,0 +1,94 @@
package com.ruoyi.common.encrypt.core;
import cn.hutool.core.util.ReflectUtil;
import com.ruoyi.common.encrypt.annotation.EncryptField;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* 加密管理类
*
* @author 老马
* @version 4.6.0
*/
@Slf4j
public class EncryptorManager {
/**
* 缓存加密器
*/
Map<EncryptContext, IEncryptor> encryptorMap = new ConcurrentHashMap<>();
/**
* 类加密字段缓存
*/
Map<Class<?>, Set<Field>> fieldCache = new ConcurrentHashMap<>();
/**
* 获取类加密字段缓存
*/
public Set<Field> getFieldCache(Class<?> sourceClazz) {
return fieldCache.computeIfAbsent(sourceClazz, clazz -> {
Field[] declaredFields = clazz.getDeclaredFields();
Set<Field> fieldSet = Arrays.stream(declaredFields).filter(field ->
field.isAnnotationPresent(EncryptField.class) && field.getType() == String.class)
.collect(Collectors.toSet());
for (Field field : fieldSet) {
field.setAccessible(true);
}
return fieldSet;
});
}
/**
* 注册加密执行者到缓存
*
* @param encryptContext 加密执行者需要的相关配置参数
*/
public IEncryptor registAndGetEncryptor(EncryptContext encryptContext) {
if (encryptorMap.containsKey(encryptContext)) {
return encryptorMap.get(encryptContext);
}
IEncryptor encryptor = ReflectUtil.newInstance(encryptContext.getAlgorithm().getClazz(), encryptContext);
encryptorMap.put(encryptContext, encryptor);
return encryptor;
}
/**
* 移除缓存中的加密执行者
*
* @param encryptContext 加密执行者需要的相关配置参数
*/
public void removeEncryptor(EncryptContext encryptContext) {
this.encryptorMap.remove(encryptContext);
}
/**
* 根据配置进行加密会进行本地缓存对应的算法和对应的秘钥信息
*
* @param value 待加密的值
* @param encryptContext 加密相关的配置信息
*/
public String encrypt(String value, EncryptContext encryptContext) {
IEncryptor encryptor = this.registAndGetEncryptor(encryptContext);
return encryptor.encrypt(value, encryptContext.getEncode());
}
/**
* 根据配置进行解密
*
* @param value 待解密的值
* @param encryptContext 加密相关的配置信息
*/
public String decrypt(String value, EncryptContext encryptContext) {
IEncryptor encryptor = this.registAndGetEncryptor(encryptContext);
return encryptor.decrypt(value);
}
}

View File

@ -0,0 +1,35 @@
package com.ruoyi.common.encrypt.core;
import com.ruoyi.common.encrypt.enumd.AlgorithmType;
import com.ruoyi.common.encrypt.enumd.EncodeType;
/**
* 加解者
*
* @author 老马
* @version 4.6.0
*/
public interface IEncryptor {
/**
* 获得当前算法
*/
AlgorithmType algorithm();
/**
* 加密
*
* @param value 待加密字符串
* @param encodeType 加密后的编码格式
* @return 加密后的字符串
*/
String encrypt(String value, EncodeType encodeType);
/**
* 解密
*
* @param value 待加密字符串
* @return 解密后的字符串
*/
String decrypt(String value);
}

View File

@ -0,0 +1,18 @@
package com.ruoyi.common.encrypt.core.encryptor;
import com.ruoyi.common.encrypt.core.EncryptContext;
import com.ruoyi.common.encrypt.core.IEncryptor;
/**
* 所有加密执行者的基类
*
* @author 老马
* @version 4.6.0
*/
public abstract class AbstractEncryptor implements IEncryptor {
public AbstractEncryptor(EncryptContext context) {
// 用户配置校验与配置注入
}
}

View File

@ -0,0 +1,69 @@
package com.ruoyi.common.encrypt.core.encryptor;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import com.ruoyi.common.encrypt.core.EncryptContext;
import com.ruoyi.common.encrypt.enumd.AlgorithmType;
import com.ruoyi.common.encrypt.enumd.EncodeType;
import java.nio.charset.StandardCharsets;
/**
* AES算法实现
*
* @author 老马
* @version 4.6.0
*/
public class AesEncryptor extends AbstractEncryptor {
private final AES aes;
public AesEncryptor(EncryptContext context) {
super(context);
String password = context.getPassword();
if (StrUtil.isBlank(password)) {
throw new IllegalArgumentException("AES没有获得秘钥信息");
}
// aes算法的秘钥要求是16位24位32位
int[] array = {16, 24, 32};
if (!ArrayUtil.contains(array, password.length())) {
throw new IllegalArgumentException("AES秘钥长度应该为16位、24位、32位实际为" + password.length() + "");
}
aes = SecureUtil.aes(context.getPassword().getBytes(StandardCharsets.UTF_8));
}
/**
* 获得当前算法
*/
@Override
public AlgorithmType algorithm() {
return AlgorithmType.AES;
}
/**
* 加密
*
* @param value 待加密字符串
* @param encodeType 加密后的编码格式
*/
@Override
public String encrypt(String value, EncodeType encodeType) {
if (encodeType == EncodeType.HEX) {
return aes.encryptHex(value);
} else {
return aes.encryptBase64(value);
}
}
/**
* 解密
*
* @param value 待加密字符串
*/
@Override
public String decrypt(String value) {
return this.aes.decryptStr(value);
}
}

View File

@ -0,0 +1,48 @@
package com.ruoyi.common.encrypt.core.encryptor;
import cn.hutool.core.codec.Base64;
import com.ruoyi.common.encrypt.core.EncryptContext;
import com.ruoyi.common.encrypt.enumd.AlgorithmType;
import com.ruoyi.common.encrypt.enumd.EncodeType;
/**
* Base64算法实现
*
* @author 老马
* @version 4.6.0
*/
public class Base64Encryptor extends AbstractEncryptor {
public Base64Encryptor(EncryptContext context) {
super(context);
}
/**
* 获得当前算法
*/
@Override
public AlgorithmType algorithm() {
return AlgorithmType.BASE64;
}
/**
* 加密
*
* @param value 待加密字符串
* @param encodeType 加密后的编码格式
*/
@Override
public String encrypt(String value, EncodeType encodeType) {
return Base64.encode(value);
}
/**
* 解密
*
* @param value 待加密字符串
*/
@Override
public String decrypt(String value) {
return Base64.decodeStr(value);
}
}

View File

@ -0,0 +1,65 @@
package com.ruoyi.common.encrypt.core.encryptor;
import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.encrypt.core.EncryptContext;
import com.ruoyi.common.encrypt.enumd.AlgorithmType;
import com.ruoyi.common.encrypt.enumd.EncodeType;
/**
* RSA算法实现
*
* @author 老马
* @version 4.6.0
*/
public class RsaEncryptor extends AbstractEncryptor {
private final RSA rsa;
public RsaEncryptor(EncryptContext context) {
super(context);
String privateKey = context.getPrivateKey();
String publicKey = context.getPublicKey();
if (StringUtils.isAnyEmpty(privateKey, publicKey)) {
throw new IllegalArgumentException("RSA公私钥均需要提供公钥加密私钥解密。");
}
this.rsa = SecureUtil.rsa(Base64.decode(privateKey), Base64.decode(publicKey));
}
/**
* 获得当前算法
*/
@Override
public AlgorithmType algorithm() {
return AlgorithmType.RSA;
}
/**
* 加密
*
* @param value 待加密字符串
* @param encodeType 加密后的编码格式
*/
@Override
public String encrypt(String value, EncodeType encodeType) {
if (encodeType == EncodeType.HEX) {
return rsa.encryptHex(value, KeyType.PublicKey);
} else {
return rsa.encryptBase64(value, KeyType.PublicKey);
}
}
/**
* 解密
*
* @param value 待加密字符串
*/
@Override
public String decrypt(String value) {
return this.rsa.decryptStr(value, KeyType.PrivateKey);
}
}

View File

@ -0,0 +1,64 @@
package com.ruoyi.common.encrypt.core.encryptor;
import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.encrypt.core.EncryptContext;
import com.ruoyi.common.encrypt.enumd.AlgorithmType;
import com.ruoyi.common.encrypt.enumd.EncodeType;
/**
* sm2算法实现
*
* @author 老马
* @version 4.6.0
*/
public class Sm2Encryptor extends AbstractEncryptor {
private final SM2 sm2;
public Sm2Encryptor(EncryptContext context) {
super(context);
String privateKey = context.getPrivateKey();
String publicKey = context.getPublicKey();
if (StringUtils.isAnyEmpty(privateKey, publicKey)) {
throw new IllegalArgumentException("SM2公私钥均需要提供公钥加密私钥解密。");
}
this.sm2 = SmUtil.sm2(Base64.decode(privateKey), Base64.decode(publicKey));
}
/**
* 获得当前算法
*/
@Override
public AlgorithmType algorithm() {
return AlgorithmType.SM2;
}
/**
* 加密
*
* @param value 待加密字符串
* @param encodeType 加密后的编码格式
*/
@Override
public String encrypt(String value, EncodeType encodeType) {
if (encodeType == EncodeType.HEX) {
return sm2.encryptHex(value, KeyType.PublicKey);
} else {
return sm2.encryptBase64(value, KeyType.PublicKey);
}
}
/**
* 解密
*
* @param value 待加密字符串
*/
@Override
public String decrypt(String value) {
return this.sm2.decryptStr(value, KeyType.PrivateKey);
}
}

View File

@ -0,0 +1,67 @@
package com.ruoyi.common.encrypt.core.encryptor;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.symmetric.SM4;
import com.ruoyi.common.encrypt.core.EncryptContext;
import com.ruoyi.common.encrypt.enumd.AlgorithmType;
import com.ruoyi.common.encrypt.enumd.EncodeType;
import java.nio.charset.StandardCharsets;
/**
* sm4算法实现
*
* @author 老马
* @version 4.6.0
*/
public class Sm4Encryptor extends AbstractEncryptor {
private final SM4 sm4;
public Sm4Encryptor(EncryptContext context) {
super(context);
String password = context.getPassword();
if (StrUtil.isBlank(password)) {
throw new IllegalArgumentException("SM4没有获得秘钥信息");
}
// sm4算法的秘钥要求是16位长度
if (16 != password.length()) {
throw new IllegalArgumentException("SM4秘钥长度应该为16位实际为" + password.length() + "");
}
this.sm4 = SmUtil.sm4(password.getBytes(StandardCharsets.UTF_8));
}
/**
* 获得当前算法
*/
@Override
public AlgorithmType algorithm() {
return AlgorithmType.SM4;
}
/**
* 加密
*
* @param value 待加密字符串
* @param encodeType 加密后的编码格式
*/
@Override
public String encrypt(String value, EncodeType encodeType) {
if (encodeType == EncodeType.HEX) {
return sm4.encryptHex(value);
} else {
return sm4.encryptBase64(value);
}
}
/**
* 解密
*
* @param value 待加密字符串
*/
@Override
public String decrypt(String value) {
return this.sm4.decryptStr(value);
}
}

View File

@ -0,0 +1,48 @@
package com.ruoyi.common.encrypt.enumd;
import com.ruoyi.common.encrypt.core.encryptor.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 算法名称
*
* @author 老马
* @version 4.6.0
*/
@Getter
@AllArgsConstructor
public enum AlgorithmType {
/**
* 默认走yml配置
*/
DEFAULT(null),
/**
* base64
*/
BASE64(Base64Encryptor.class),
/**
* aes
*/
AES(AesEncryptor.class),
/**
* rsa
*/
RSA(RsaEncryptor.class),
/**
* sm2
*/
SM2(Sm2Encryptor.class),
/**
* sm4
*/
SM4(Sm4Encryptor.class);
private final Class<? extends AbstractEncryptor> clazz;
}

View File

@ -0,0 +1,26 @@
package com.ruoyi.common.encrypt.enumd;
/**
* 编码类型
*
* @author 老马
* @version 4.6.0
*/
public enum EncodeType {
/**
* 默认使用yml配置
*/
DEFAULT,
/**
* base64编码
*/
BASE64,
/**
* 16进制编码
*/
HEX;
}

View File

@ -0,0 +1,108 @@
package com.ruoyi.common.encrypt.interceptor;
import cn.hutool.core.collection.CollectionUtil;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.encrypt.annotation.EncryptField;
import com.ruoyi.common.encrypt.core.EncryptContext;
import com.ruoyi.common.encrypt.core.EncryptorManager;
import com.ruoyi.common.encrypt.enumd.AlgorithmType;
import com.ruoyi.common.encrypt.enumd.EncodeType;
import com.ruoyi.common.encrypt.properties.EncryptorProperties;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.*;
import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* 出参解密拦截器
*
* @author 老马
* @version 4.6.0
*/
@Slf4j
@Intercepts({@Signature(
type = ResultSetHandler.class,
method = "handleResultSets",
args = {Statement.class})
})
@AllArgsConstructor
public class MybatisDecryptInterceptor implements Interceptor {
private final EncryptorManager encryptorManager;
private final EncryptorProperties defaultProperties;
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 获取执行mysql执行结果
Object result = invocation.proceed();
if (result == null) {
return null;
}
decryptHandler(result);
return result;
}
/**
* 解密对象
*
* @param sourceObject 待加密对象
*/
private void decryptHandler(Object sourceObject) {
if (sourceObject instanceof Map) {
((Map<?, Object>) sourceObject).values().forEach(this::decryptHandler);
return;
}
if (sourceObject instanceof List) {
// 判断第一个元素是否含有注解如果没有直接返回提高效率
Object firstItem = ((List<?>) sourceObject).get(0);
if (CollectionUtil.isEmpty(encryptorManager.getFieldCache(firstItem.getClass()))) {
return;
}
((List<?>) sourceObject).forEach(this::decryptHandler);
return;
}
Set<Field> fields = encryptorManager.getFieldCache(sourceObject.getClass());
try {
for (Field field : fields) {
field.set(sourceObject, this.decryptField(String.valueOf(field.get(sourceObject)), field));
}
} catch (Exception e) {
log.error("处理解密字段时出错", e);
}
}
/**
* 字段值进行加密通过字段的批注注册新的加密算法
*
* @param value 待加密的值
* @param field 待加密字段
* @return 加密后结果
*/
private String decryptField(String value, Field field) {
EncryptField encryptField = field.getAnnotation(EncryptField.class);
EncryptContext encryptContext = new EncryptContext();
encryptContext.setAlgorithm(encryptField.algorithm() == AlgorithmType.DEFAULT ? defaultProperties.getAlgorithm() : encryptField.algorithm());
encryptContext.setEncode(encryptField.encode() == EncodeType.DEFAULT ? defaultProperties.getEncode() : encryptField.encode());
encryptContext.setPassword(StringUtils.isBlank(encryptField.password()) ? defaultProperties.getPassword() : encryptField.password());
encryptContext.setPrivateKey(StringUtils.isBlank(encryptField.privateKey()) ? defaultProperties.getPrivateKey() : encryptField.privateKey());
encryptContext.setPublicKey(StringUtils.isBlank(encryptField.publicKey()) ? defaultProperties.getPublicKey() : encryptField.publicKey());
return this.encryptorManager.decrypt(value, encryptContext);
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}

View File

@ -0,0 +1,115 @@
package com.ruoyi.common.encrypt.interceptor;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.encrypt.annotation.EncryptField;
import com.ruoyi.common.encrypt.core.EncryptContext;
import com.ruoyi.common.encrypt.core.EncryptorManager;
import com.ruoyi.common.encrypt.enumd.AlgorithmType;
import com.ruoyi.common.encrypt.enumd.EncodeType;
import com.ruoyi.common.encrypt.properties.EncryptorProperties;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* 入参加密拦截器
*
* @author 老马
* @version 4.6.0
*/
@Slf4j
@Intercepts({@Signature(
type = ParameterHandler.class,
method = "setParameters",
args = {PreparedStatement.class})
})
@AllArgsConstructor
public class MybatisEncryptInterceptor implements Interceptor {
private final EncryptorManager encryptorManager;
private final EncryptorProperties defaultProperties;
@Override
public Object intercept(Invocation invocation) throws Throwable {
return invocation;
}
@Override
public Object plugin(Object target) {
if (target instanceof ParameterHandler) {
// 进行加密操作
ParameterHandler parameterHandler = (ParameterHandler) target;
Object parameterObject = parameterHandler.getParameterObject();
if (ObjectUtil.isNotNull(parameterObject) && !(parameterObject instanceof String)) {
this.encryptHandler(parameterObject);
}
}
return target;
}
/**
* 加密对象
*
* @param sourceObject 待加密对象
*/
@SuppressWarnings("unchecked cast")
private void encryptHandler(Object sourceObject) {
if (sourceObject instanceof Map) {
((Map<?, Object>) sourceObject).values().forEach(this::encryptHandler);
return;
}
if (sourceObject instanceof List) {
// 判断第一个元素是否含有注解如果没有直接返回提高效率
Object firstItem = ((List<?>) sourceObject).get(0);
if (CollectionUtil.isEmpty(encryptorManager.getFieldCache(firstItem.getClass()))) {
return;
}
((List<?>) sourceObject).forEach(this::encryptHandler);
return;
}
Set<Field> fields = encryptorManager.getFieldCache(sourceObject.getClass());
try {
for (Field field : fields) {
field.set(sourceObject, this.encryptField(String.valueOf(field.get(sourceObject)), field));
}
} catch (Exception e) {
log.error("处理加密字段时出错", e);
}
}
/**
* 字段值进行加密通过字段的批注注册新的加密算法
*
* @param value 待加密的值
* @param field 待加密字段
* @return 加密后结果
*/
private String encryptField(String value, Field field) {
EncryptField encryptField = field.getAnnotation(EncryptField.class);
EncryptContext encryptContext = new EncryptContext();
encryptContext.setAlgorithm(encryptField.algorithm() == AlgorithmType.DEFAULT ? defaultProperties.getAlgorithm() : encryptField.algorithm());
encryptContext.setEncode(encryptField.encode() == EncodeType.DEFAULT ? defaultProperties.getEncode() : encryptField.encode());
encryptContext.setPassword(StringUtils.isBlank(encryptField.password()) ? defaultProperties.getPassword() : encryptField.password());
encryptContext.setPrivateKey(StringUtils.isBlank(encryptField.privateKey()) ? defaultProperties.getPrivateKey() : encryptField.privateKey());
encryptContext.setPublicKey(StringUtils.isBlank(encryptField.publicKey()) ? defaultProperties.getPublicKey() : encryptField.publicKey());
return this.encryptorManager.encrypt(value, encryptContext);
}
@Override
public void setProperties(Properties properties) {
}
}

View File

@ -0,0 +1,50 @@
package com.ruoyi.common.encrypt.properties;
import com.ruoyi.common.encrypt.enumd.AlgorithmType;
import com.ruoyi.common.encrypt.enumd.EncodeType;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 加解密属性配置类
*
* @author 老马
* @version 4.6.0
*/
@Data
@Component
@ConfigurationProperties(prefix = "mybatis-encryptor")
public class EncryptorProperties {
/**
* 过滤开关
*/
private Boolean enable;
/**
* 默认算法
*/
private AlgorithmType algorithm;
/**
* 安全秘钥
*/
private String password;
/**
* 公钥
*/
private String publicKey;
/**
* 私钥
*/
private String privateKey;
/**
* 编码方式base64/hex
*/
private EncodeType encode;
}

View File

@ -0,0 +1 @@
com.ruoyi.common.encrypt.config.EncryptorAutoConfiguration

View File

@ -22,6 +22,8 @@ public class OssUrlTranslationImpl implements TranslationInterface {
public String translation(Object key, String other) { public String translation(Object key, String other) {
if (key instanceof String ids) { if (key instanceof String ids) {
return ossService.selectUrlByIds(ids); return ossService.selectUrlByIds(ids);
} else if (key instanceof Long id) {
return ossService.selectUrlByIds(id.toString());
} }
return null; return null;
} }

View File

@ -83,6 +83,11 @@
<artifactId>ruoyi-common-sensitive</artifactId> <artifactId>ruoyi-common-sensitive</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-encrypt</artifactId>
</dependency>
<!-- 短信 用哪个导入哪个依赖 --> <!-- 短信 用哪个导入哪个依赖 -->
<!-- <dependency>--> <!-- <dependency>-->
<!-- <groupId>com.aliyun</groupId>--> <!-- <groupId>com.aliyun</groupId>-->

View File

@ -0,0 +1,55 @@
package com.ruoyi.demo.controller;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.demo.domain.TestDemoEncrypt;
import com.ruoyi.demo.mapper.TestDemoEncryptMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* 测试数据库加解密功能
*
* @author Lion Li
*/
@Validated
@RestController
@RequestMapping("/demo/encrypt")
public class TestEncryptController {
@Autowired
private TestDemoEncryptMapper mapper;
@Value("${mybatis-encryptor.enable}")
private Boolean encryptEnable;
/**
* 测试数据库加解密
*
* @param key 测试key
* @param value 测试value
*/
@GetMapping()
public R<Map<String, TestDemoEncrypt>> test(String key, String value) {
if (!encryptEnable) {
throw new RuntimeException("加密功能未开启!");
}
Map<String, TestDemoEncrypt> map = new HashMap<>(2);
TestDemoEncrypt demo = new TestDemoEncrypt();
demo.setTestKey(key);
demo.setValue(value);
mapper.insert(demo);
map.put("加密", demo);
TestDemoEncrypt testDemo = mapper.selectById(demo.getId());
map.put("解密", testDemo);
return R.ok(map);
}
}

View File

@ -0,0 +1,29 @@
package com.ruoyi.demo.domain;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.encrypt.annotation.EncryptField;
import com.ruoyi.common.encrypt.enumd.AlgorithmType;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("test_demo")
public class TestDemoEncrypt extends TestDemo {
/**
* key键
*/
// @EncryptField(algorithm=AlgorithmType.SM2, privateKey = "MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgZSlOvw8FBiH+aFJWLYZP/VRjg9wjfRarTkGBZd/T3N+gCgYIKoEcz1UBgi2hRANCAAR5DGuQwJqkxnbCsP+iPSDoHWIF4RwcR5EsSvT8QPxO1wRkR2IhCkzvRb32x2CUgJFdvoqVqfApFDPZzShqzBwX", publicKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEeQxrkMCapMZ2wrD/oj0g6B1iBeEcHEeRLEr0/ED8TtcEZEdiIQpM70W99sdglICRXb6KlanwKRQz2c0oaswcFw==")
@EncryptField(algorithm = AlgorithmType.RSA, privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBANBBEeueWlXlkkj2+WY5l+IWe42d8b5K28g+G/CFKC/yYAEHtqGlCsBOrb+YBkG9mPzmuYA/n9k0NFIc8E8yY5vZQaroyFBrTTWEzG9RY2f7Y3svVyybs6jpXSUs4xff8abo7wL1Y/wUaeatTViamxYnyTvdTmLm3d+JjRij68rxAgMBAAECgYAB0TnhXraSopwIVRfmboea1b0upl+BUdTJcmci412UjrKr5aE695ZLPkXbFXijVu7HJlyyv94NVUdaMACV7Ku/S2RuNB70M7YJm8rAjHFC3/i2ZeIM60h1Ziy4QKv0XM3pRATlDCDNhC1WUrtQCQSgU8kcp6eUUppruOqDzcY04QJBAPm9+sBP9CwDRgy3e5+V8aZtJkwDstb0lVVV/KY890cydVxiCwvX3fqVnxKMlb+x0YtH0sb9v+71xvK2lGobaRECQQDVePU6r/cCEfpc+nkWF6osAH1f8Mux3rYv2DoBGvaPzV2BGfsLed4neRfCwWNCKvGPCdW+L0xMJg8+RwaoBUPhAkAT5kViqXxFPYWJYd1h2+rDXhMdH3ZSlm6HvDBDdrwlWinr0Iwcx3iSjPV93uHXwm118aUj4fg3LDJMCKxOwBxhAkByrQXfvwOMYygBprRBf/j0plazoWFrbd6lGR0f1uI5IfNnFRPdeFw1DEINZ2Hw+6zEUF44SqRMC+4IYJNc02dBAkBCgy7RvfyV/A7N6kKXxTHauY0v6XwSSvpeKtRJkbIcRWOdIYvaHO9L7cklj3vIEdwjSUp9K4VTBYYlmAz1xh03", publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQQRHrnlpV5ZJI9vlmOZfiFnuNnfG+StvIPhvwhSgv8mABB7ahpQrATq2/mAZBvZj85rmAP5/ZNDRSHPBPMmOb2UGq6MhQa001hMxvUWNn+2N7L1csm7Oo6V0lLOMX3/Gm6O8C9WP8FGnmrU1YmpsWJ8k73U5i5t3fiY0Yo+vK8QIDAQAB")
private String testKey;
/**
*
*/
// @EncryptField // 什么也不写走默认yml配置
// @EncryptField(algorithm = AlgorithmType.SM4, password = "10rfylhtccpuyke5")
@EncryptField(algorithm = AlgorithmType.AES, password = "10rfylhtccpuyke5")
private String value;
}

View File

@ -0,0 +1,13 @@
package com.ruoyi.demo.mapper;
import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
import com.ruoyi.demo.domain.TestDemoEncrypt;
/**
* 测试加密功能
*
* @author Lion Li
*/
public interface TestDemoEncryptMapper extends BaseMapperPlus<TestDemoEncryptMapper, TestDemoEncrypt, TestDemoEncrypt> {
}

View File

@ -1,6 +1,7 @@
package com.ruoyi.system.controller.system; package com.ruoyi.system.controller.system;
import cn.dev33.satoken.secure.BCrypt; import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.FileUtil;
import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
@ -11,6 +12,7 @@ import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.satoken.utils.LoginHelper; import com.ruoyi.common.satoken.utils.LoginHelper;
import com.ruoyi.common.web.core.BaseController; import com.ruoyi.common.web.core.BaseController;
import com.ruoyi.system.domain.bo.SysUserBo; import com.ruoyi.system.domain.bo.SysUserBo;
import com.ruoyi.system.domain.bo.SysUserProfileBo;
import com.ruoyi.system.domain.vo.AvatarVo; import com.ruoyi.system.domain.vo.AvatarVo;
import com.ruoyi.system.domain.vo.ProfileVo; import com.ruoyi.system.domain.vo.ProfileVo;
import com.ruoyi.system.domain.vo.SysOssVo; import com.ruoyi.system.domain.vo.SysOssVo;
@ -57,7 +59,8 @@ public class SysProfileController extends BaseController {
*/ */
@Log(title = "个人信息", businessType = BusinessType.UPDATE) @Log(title = "个人信息", businessType = BusinessType.UPDATE)
@PutMapping @PutMapping
public R<Void> updateProfile(@RequestBody SysUserBo user) { public R<Void> updateProfile(@RequestBody SysUserProfileBo profile) {
SysUserBo user = BeanUtil.copyProperties(profile, SysUserBo.class);
if (StringUtils.isNotEmpty(user.getPhonenumber()) if (StringUtils.isNotEmpty(user.getPhonenumber())
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) { && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
return R.fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); return R.fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
@ -67,10 +70,6 @@ public class SysProfileController extends BaseController {
return R.fail("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); return R.fail("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
} }
user.setUserId(LoginHelper.getUserId()); user.setUserId(LoginHelper.getUserId());
user.setUserName(null);
user.setPassword(null);
user.setAvatar(null);
user.setDeptId(null);
if (userService.updateUserProfile(user) > 0) { if (userService.updateUserProfile(user) > 0) {
return R.ok(); return R.ok();
} }
@ -117,7 +116,7 @@ public class SysProfileController extends BaseController {
} }
SysOssVo oss = iSysOssService.upload(avatarfile); SysOssVo oss = iSysOssService.upload(avatarfile);
String avatar = oss.getUrl(); String avatar = oss.getUrl();
if (userService.updateUserAvatar(LoginHelper.getUsername(), avatar)) { if (userService.updateUserAvatar(LoginHelper.getUsername(), oss.getOssId())) {
AvatarVo avatarVo = new AvatarVo(); AvatarVo avatarVo = new AvatarVo();
avatarVo.setImgUrl(avatar); avatarVo.setImgUrl(avatar);
return R.ok(avatarVo); return R.ok(avatarVo);

View File

@ -65,7 +65,7 @@ public class SysUser extends BaseEntity {
/** /**
* 用户头像 * 用户头像
*/ */
private String avatar; private Long avatar;
/** /**
* 密码 * 密码

View File

@ -13,22 +13,31 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class SysOssBo extends BaseEntity { public class SysOssBo extends BaseEntity {
/**
* ossId
*/
private Long ossId;
/** /**
* 文件名 * 文件名
*/ */
private String fileName; private String fileName;
/** /**
* 原名 * 原名
*/ */
private String originalName; private String originalName;
/** /**
* 文件后缀名 * 文件后缀名
*/ */
private String fileSuffix; private String fileSuffix;
/** /**
* URL地址 * URL地址
*/ */
private String url; private String url;
/** /**
* 服务商 * 服务商
*/ */

View File

@ -77,7 +77,7 @@ public class SysUserBo extends BaseEntity {
/** /**
* 头像地址 * 头像地址
*/ */
private String avatar; private Long avatar;
/** /**
* 密码 * 密码

View File

@ -0,0 +1,55 @@
package com.ruoyi.system.domain.bo;
import com.ruoyi.common.core.xss.Xss;
import com.ruoyi.common.mybatis.core.domain.BaseEntity;
import com.ruoyi.common.sensitive.annotation.Sensitive;
import com.ruoyi.common.sensitive.core.SensitiveStrategy;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* 个人信息业务处理
*
* @author Michelle.Chung
*/
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class SysUserProfileBo extends BaseEntity {
/**
* 用户ID
*/
private Long userId;
/**
* 用户昵称
*/
@Xss(message = "用户昵称不能包含脚本字符")
@Size(min = 0, max = 30, message = "用户昵称长度不能超过{max}个字符")
private String nickName;
/**
* 用户邮箱
*/
@Sensitive(strategy = SensitiveStrategy.EMAIL)
@Email(message = "邮箱格式不正确")
@Size(min = 0, max = 50, message = "邮箱长度不能超过{max}个字符")
private String email;
/**
* 手机号码
*/
@Sensitive(strategy = SensitiveStrategy.PHONE)
private String phonenumber;
/**
* 用户性别0男 1女 2未知
*/
private String sex;
}

View File

@ -1,6 +1,8 @@
package com.ruoyi.system.domain.vo; package com.ruoyi.system.domain.vo;
import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.translation.annotation.Translation;
import com.ruoyi.common.translation.constant.TransConstant;
import lombok.Data; import lombok.Data;
import java.io.Serial; import java.io.Serial;
@ -63,7 +65,8 @@ public class SysUserVo implements Serializable {
/** /**
* 头像地址 * 头像地址
*/ */
private String avatar; @Translation(type = TransConstant.OSS_ID_TO_URL)
private Long avatar;
/** /**
* 密码 * 密码

View File

@ -174,7 +174,7 @@ public interface ISysUserService {
* @param avatar 头像地址 * @param avatar 头像地址
* @return 结果 * @return 结果
*/ */
boolean updateUserAvatar(String userName, String avatar); boolean updateUserAvatar(String userName, Long avatar);
/** /**
* 重置用户密码 * 重置用户密码

View File

@ -373,7 +373,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
* @return 结果 * @return 结果
*/ */
@Override @Override
public boolean updateUserAvatar(String userName, String avatar) { public boolean updateUserAvatar(String userName, Long avatar) {
return baseMapper.update(null, return baseMapper.update(null,
new LambdaUpdateWrapper<SysUser>() new LambdaUpdateWrapper<SysUser>()
.set(SysUser::getAvatar, avatar) .set(SysUser::getAvatar, avatar)

View File

@ -155,7 +155,7 @@ create table sys_user (
email varchar2(50) default '', email varchar2(50) default '',
phonenumber varchar2(11) default '', phonenumber varchar2(11) default '',
sex char(1) default '0', sex char(1) default '0',
avatar varchar2(100) default '', avatar number(20) default null,
password varchar2(100) default '', password varchar2(100) default '',
status char(1) default '0', status char(1) default '0',
del_flag char(1) default '0', del_flag char(1) default '0',
@ -197,8 +197,8 @@ comment on column sys_user.remark is '备注';
-- ---------------------------- -- ----------------------------
-- 初始化-用户信息表数据 -- 初始化-用户信息表数据
-- ---------------------------- -- ----------------------------
insert into sys_user values(1, '000000', 103, 'admin', '疯狂的狮子Li', 'sys_user', 'crazyLionLi@163.com', '15888888888', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate, 103, 1, sysdate, null, null, '管理员'); insert into sys_user values(1, '000000', 103, 'admin', '疯狂的狮子Li', 'sys_user', 'crazyLionLi@163.com', '15888888888', '1', null, '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate, 103, 1, sysdate, null, null, '管理员');
insert into sys_user values(2, '000000', 105, 'lionli', '疯狂的狮子Li', 'sys_user', 'crazyLionLi@qq.com', '15666666666', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate, 103, 1, sysdate, null, null, '测试员'); insert into sys_user values(2, '000000', 105, 'lionli', '疯狂的狮子Li', 'sys_user', 'crazyLionLi@qq.com', '15666666666', '1', null, '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate, 103, 1, sysdate, null, null, '测试员');
-- ---------------------------- -- ----------------------------

View File

@ -162,7 +162,7 @@ create table if not exists sys_user
email varchar(50) default ''::varchar, email varchar(50) default ''::varchar,
phonenumber varchar(11) default ''::varchar, phonenumber varchar(11) default ''::varchar,
sex char default '0'::bpchar, sex char default '0'::bpchar,
avatar varchar(100) default ''::varchar, avatar int8,
password varchar(100) default ''::varchar, password varchar(100) default ''::varchar,
status char default '0'::bpchar, status char default '0'::bpchar,
del_flag char default '0'::bpchar, del_flag char default '0'::bpchar,
@ -204,8 +204,8 @@ comment on column sys_user.remark is '备注';
-- 初始化-用户信息表数据 -- 初始化-用户信息表数据
-- ---------------------------- -- ----------------------------
insert into sys_user values(1, '000000', 103, 'admin', '疯狂的狮子Li', 'sys_user', 'crazyLionLi@163.com', '15888888888', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', now(), 103, 1, now(), null, null, '管理员'); insert into sys_user values(1, '000000', 103, 'admin', '疯狂的狮子Li', 'sys_user', 'crazyLionLi@163.com', '15888888888', '1', null, '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', now(), 103, 1, now(), null, null, '管理员');
insert into sys_user values(2, '000000', 105, 'lionli', '疯狂的狮子Li', 'sys_user', 'crazyLionLi@qq.com', '15666666666', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', now(), 103, 1, now(), null, null, '测试员'); insert into sys_user values(2, '000000', 105, 'lionli', '疯狂的狮子Li', 'sys_user', 'crazyLionLi@qq.com', '15666666666', '1', null, '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', now(), 103, 1, now(), null, null, '测试员');
-- ---------------------------- -- ----------------------------

View File

@ -109,7 +109,7 @@ create table sys_user (
email varchar(50) default '' comment '用户邮箱', email varchar(50) default '' comment '用户邮箱',
phonenumber varchar(11) default '' comment '手机号码', phonenumber varchar(11) default '' comment '手机号码',
sex char(1) default '0' comment '用户性别0男 1女 2未知', sex char(1) default '0' comment '用户性别0男 1女 2未知',
avatar varchar(100) default '' comment '头像地址', avatar bigint(20) comment '头像地址',
password varchar(100) default '' comment '密码', password varchar(100) default '' comment '密码',
status char(1) default '0' comment '帐号状态0正常 1停用', status char(1) default '0' comment '帐号状态0正常 1停用',
del_flag char(1) default '0' comment '删除标志0代表存在 2代表删除', del_flag char(1) default '0' comment '删除标志0代表存在 2代表删除',
@ -127,8 +127,8 @@ create table sys_user (
-- ---------------------------- -- ----------------------------
-- 初始化-用户信息表数据 -- 初始化-用户信息表数据
-- ---------------------------- -- ----------------------------
insert into sys_user values(1, '000000', 103, 'admin', '疯狂的狮子Li', 'sys_user', 'crazyLionLi@163.com', '15888888888', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), 103, 1, sysdate(), null, null, '管理员'); insert into sys_user values(1, '000000', 103, 'admin', '疯狂的狮子Li', 'sys_user', 'crazyLionLi@163.com', '15888888888', '1', null, '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), 103, 1, sysdate(), null, null, '管理员');
insert into sys_user values(2, '000000', 105, 'lionli', '疯狂的狮子Li', 'sys_user', 'crazyLionLi@qq.com', '15666666666', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), 103, 1, sysdate(), null, null, '测试员'); insert into sys_user values(2, '000000', 105, 'lionli', '疯狂的狮子Li', 'sys_user', 'crazyLionLi@qq.com', '15666666666', '1', null, '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), 103, 1, sysdate(), null, null, '测试员');
-- ---------------------------- -- ----------------------------

View File

@ -2273,7 +2273,7 @@ CREATE TABLE [sys_user]
[email] nvarchar(50) DEFAULT '' NULL, [email] nvarchar(50) DEFAULT '' NULL,
[phonenumber] nvarchar(11) DEFAULT '' NULL, [phonenumber] nvarchar(11) DEFAULT '' NULL,
[sex] nchar(1) DEFAULT ('0') NULL, [sex] nchar(1) DEFAULT ('0') NULL,
[avatar] nvarchar(100) DEFAULT '' NULL, [avatar] bigint NULL,
[password] nvarchar(100) DEFAULT '' NULL, [password] nvarchar(100) DEFAULT '' NULL,
[status] nchar(1) DEFAULT ('0') NULL, [status] nchar(1) DEFAULT ('0') NULL,
[del_flag] nchar(1) DEFAULT ('0') NULL, [del_flag] nchar(1) DEFAULT ('0') NULL,
@ -2424,9 +2424,9 @@ EXEC sys.sp_addextendedproperty
'TABLE', N'sys_user' 'TABLE', N'sys_user'
GO GO
INSERT [sys_user] ([user_id], [tenant_id], [dept_id], [user_name], [nick_name], [user_type], [email], [phonenumber], [sex], [avatar], [password], [status], [del_flag], [login_ip], [login_date], [create_dept], [create_by], [create_time], [update_by], [update_time], [remark]) VALUES (1, 103, N'000000', N'admin', N'疯狂的狮子Li', N'sys_user', N'crazyLionLi@163.com', N'15888888888', N'1', N'', N'$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', N'0', N'0', N'127.0.0.1', getdate(), 103, 1, getdate(), NULL, NULL, N'管理员') INSERT [sys_user] ([user_id], [tenant_id], [dept_id], [user_name], [nick_name], [user_type], [email], [phonenumber], [sex], [avatar], [password], [status], [del_flag], [login_ip], [login_date], [create_dept], [create_by], [create_time], [update_by], [update_time], [remark]) VALUES (1, 103, N'000000', N'admin', N'疯狂的狮子Li', N'sys_user', N'crazyLionLi@163.com', N'15888888888', N'1', NULL, N'$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', N'0', N'0', N'127.0.0.1', getdate(), 103, 1, getdate(), NULL, NULL, N'管理员')
GO GO
INSERT [sys_user] ([user_id], [tenant_id], [dept_id], [user_name], [nick_name], [user_type], [email], [phonenumber], [sex], [avatar], [password], [status], [del_flag], [login_ip], [login_date], [create_dept], [create_by], [create_time], [update_by], [update_time], [remark]) VALUES (2, 105, N'000000', N'lionli', N'疯狂的狮子Li', N'sys_user', N'crazyLionLi@qq.com', N'15666666666', N'1', N'', N'$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', N'0', N'0', N'127.0.0.1', getdate(), 103, 1, getdate(), NULL, NULL, N'测试员') INSERT [sys_user] ([user_id], [tenant_id], [dept_id], [user_name], [nick_name], [user_type], [email], [phonenumber], [sex], [avatar], [password], [status], [del_flag], [login_ip], [login_date], [create_dept], [create_by], [create_time], [update_by], [update_time], [remark]) VALUES (2, 105, N'000000', N'lionli', N'疯狂的狮子Li', N'sys_user', N'crazyLionLi@qq.com', N'15666666666', N'1', NULL, N'$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', N'0', N'0', N'127.0.0.1', getdate(), 103, 1, getdate(), NULL, NULL, N'测试员')
GO GO
CREATE TABLE [sys_user_post] CREATE TABLE [sys_user_post]