Merge branch 'master' into springboot3

# Conflicts:
#	db/tables_nacos.sql
#	jeecg-boot-base-core/pom.xml
#	jeecg-boot-base-core/src/main/java/org/jeecg/config/Swagger2Config.java
#	jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java
#	jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysFilesController.java
#	jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysRoleIndexController.java
#	jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysFiles.java
#	jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysPermissionServiceImpl.java
#	jeecg-module-system/jeecg-system-start/pom.xml
#	jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml
#	jeecg-server-cloud/jeecg-cloud-gateway/pom.xml
#	jeecg-server-cloud/jeecg-visual/jeecg-cloud-sentinel/pom.xml
#	pom.xml
This commit is contained in:
EightMonth
2024-03-25 09:39:13 +08:00
159 changed files with 22885 additions and 16825 deletions

View File

@@ -4,7 +4,7 @@
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-parent</artifactId>
<version>3.6.2</version>
<version>3.6.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-boot-base-core</artifactId>
@@ -96,7 +96,7 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.version}</version>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>

View File

@@ -22,10 +22,10 @@ public interface CommonAPI {
/**
* 2查询用户权限信息
* @param username
* @param userId
* @return
*/
Set<String> queryUserAuths(String username);
Set<String> queryUserAuths(String userId);
/**
* 3根据 id 查询数据库中存储的 DynamicDataSourceModel

View File

@@ -17,6 +17,8 @@ public class DataLogDTO {
private String type;
private String createName;
public DataLogDTO(){
}

View File

@@ -30,6 +30,13 @@ public class OnlineAuthDTO implements Serializable {
*/
private String onlineFormUrl;
//update-begin---author:chenrui ---date:20240123 for[QQYUN-7992]【online】工单申请下的online表单未配置online表单开发菜单操作报错无权限------------
/**
* online工单的地址
*/
private String onlineWorkOrderUrl;
//update-end---author:chenrui ---date:20240123 for[QQYUN-7992]【online】工单申请下的online表单未配置online表单开发菜单操作报错无权限------------
public OnlineAuthDTO(){
}

View File

@@ -293,6 +293,13 @@ public class DictAspect {
log.debug("translateDictFromTableByKeys.dictCode:" + dictCode);
log.debug("translateDictFromTableByKeys.values:" + values);
//update-begin---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
//update-begin---author:wangshuai---date:2024-01-09---for:微服务下为空报错没有参数需要传递空字符串---
if(null == dataSource){
dataSource = "";
}
//update-end---author:wangshuai---date:2024-01-09---for:微服务下为空报错没有参数需要传递空字符串---
List<DictModel> texts = commonApi.translateDictFromTableByKeys(table, text, code, values, dataSource);
//update-end---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
log.debug("translateDictFromTableByKeys.result:" + texts);

View File

@@ -377,6 +377,8 @@ public interface CommonConstant {
/**前端vue3版本Header参数名*/
String VERSION="X-Version";
String VERSION_V3 = "v3";
/**存储在线程变量里的动态表名*/
String DYNAMIC_TABLE_NAME="DYNAMIC_TABLE_NAME";
/**

View File

@@ -13,12 +13,16 @@ import java.util.List;
public enum RoleIndexConfigEnum {
/**首页自定义 admin*/
ADMIN("admin", "dashboard/Analysis"),
// ADMIN("admin", "dashboard/Analysis"),
//TEST("test", "dashboard/IndexChart"),
/**首页自定义 hr*/
HR("hr", "dashboard/IndexBdc");
// HR("hr", "dashboard/IndexBdc");
//DM("dm", "dashboard/IndexTask"),
// 注:此值仅为防止报错,无任何实际意义
ROLE_INDEX_CONFIG_ENUM("RoleIndexConfigEnumDefault", "dashboard/Analysis");
/**
* 角色编码
*/

View File

@@ -19,6 +19,8 @@ public class SysFilesModel {
private String storeType;
/**文件大小kb*/
private Double fileSize;
/**租户id*/
private String tenantId;
public String getId() {
return id;
@@ -67,4 +69,12 @@ public class SysFilesModel {
public void setFileSize(Double fileSize) {
this.fileSize = fileSize;
}
public String getTenantId() {
return tenantId;
}
public void setTenantId(String tenantId) {
this.tenantId = tenantId;
}
}

View File

@@ -28,7 +28,9 @@ import java.io.InputStream;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -346,8 +348,11 @@ public class CommonUtils {
//返回 host domain
String baseDomainPath = null;
int length = 80;
if(length == serverPort){
//update-begin---author:wangshuai---date:2024-03-15---for:【QQYUN-8561】企业微信登陆请求接口设置上下文不一致导致接口404---
int httpPort = 80;
int httpsPort = 443;
if(httpPort == serverPort || httpsPort == serverPort){
//update-end---author:wangshuai---date:2024-03-15---for:【QQYUN-8561】企业微信登陆请求接口设置上下文不一致导致接口404---~
baseDomainPath = scheme + "://" + serverName + contextPath ;
}else{
baseDomainPath = scheme + "://" + serverName + ":" + serverPort + contextPath ;
@@ -467,4 +472,19 @@ public class CommonUtils {
}
return false;
}
/**
* 输出info日志会捕获异常防止因为日志问题导致程序异常
*
* @param msg
* @param objects
*/
public static void logInfo(String msg, Object... objects) {
try {
log.info(msg, objects);
} catch (Exception e) {
log.warn("{} —— {}", msg, e.getMessage());
}
}
}

View File

@@ -62,8 +62,8 @@ public class DySmsHelper {
//update-begin-authortaoyan date:20200811 for:配置类数据获取
StaticConfig staticConfig = SpringContextUtils.getBean(StaticConfig.class);
logger.info("阿里大鱼短信秘钥 accessKeyId" + staticConfig.getAccessKeyId());
logger.info("阿里大鱼短信秘钥 accessKeySecret"+ staticConfig.getAccessKeySecret());
//logger.info("阿里大鱼短信秘钥 accessKeyId" + staticConfig.getAccessKeyId());
//logger.info("阿里大鱼短信秘钥 accessKeySecret"+ staticConfig.getAccessKeySecret());
setAccessKeyId(staticConfig.getAccessKeyId());
setAccessKeySecret(staticConfig.getAccessKeySecret());
//update-end-authortaoyan date:20200811 for:配置类数据获取

View File

@@ -1,55 +1,6 @@
package org.jeecg.common.util.sqlInjection.parse;
import net.sf.jsqlparser.expression.AllValue;
import net.sf.jsqlparser.expression.AnalyticExpression;
import net.sf.jsqlparser.expression.AnyComparisonExpression;
import net.sf.jsqlparser.expression.ArrayConstructor;
import net.sf.jsqlparser.expression.ArrayExpression;
import net.sf.jsqlparser.expression.BinaryExpression;
import net.sf.jsqlparser.expression.CaseExpression;
import net.sf.jsqlparser.expression.CastExpression;
import net.sf.jsqlparser.expression.CollateExpression;
import net.sf.jsqlparser.expression.ConnectByRootOperator;
import net.sf.jsqlparser.expression.DateTimeLiteralExpression;
import net.sf.jsqlparser.expression.DateValue;
import net.sf.jsqlparser.expression.DoubleValue;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitor;
import net.sf.jsqlparser.expression.ExtractExpression;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.HexValue;
import net.sf.jsqlparser.expression.IntervalExpression;
import net.sf.jsqlparser.expression.JdbcNamedParameter;
import net.sf.jsqlparser.expression.JdbcParameter;
import net.sf.jsqlparser.expression.JsonAggregateFunction;
import net.sf.jsqlparser.expression.JsonExpression;
import net.sf.jsqlparser.expression.JsonFunction;
import net.sf.jsqlparser.expression.JsonFunctionExpression;
import net.sf.jsqlparser.expression.KeepExpression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.MySQLGroupConcat;
import net.sf.jsqlparser.expression.NextValExpression;
import net.sf.jsqlparser.expression.NotExpression;
import net.sf.jsqlparser.expression.NullValue;
import net.sf.jsqlparser.expression.NumericBind;
import net.sf.jsqlparser.expression.OracleHierarchicalExpression;
import net.sf.jsqlparser.expression.OracleHint;
import net.sf.jsqlparser.expression.OracleNamedFunctionParameter;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.RowConstructor;
import net.sf.jsqlparser.expression.RowGetExpression;
import net.sf.jsqlparser.expression.SignedExpression;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.TimeKeyExpression;
import net.sf.jsqlparser.expression.TimeValue;
import net.sf.jsqlparser.expression.TimestampValue;
import net.sf.jsqlparser.expression.TimezoneExpression;
import net.sf.jsqlparser.expression.TryCastExpression;
import net.sf.jsqlparser.expression.UserVariable;
import net.sf.jsqlparser.expression.ValueListExpression;
import net.sf.jsqlparser.expression.VariableAssignment;
import net.sf.jsqlparser.expression.WhenClause;
import net.sf.jsqlparser.expression.XMLSerializeExpr;
import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift;
@@ -215,6 +166,23 @@ public class ConstAnalyzer implements ExpressionVisitor, ItemsListVisitor {
expr.getBetweenExpressionEnd().accept(this);
}
// /**
// * 用于处理 OverlapsCondition 类型的表达式
// * @param overlapsCondition
// */
// @Override
// public void visit(OverlapsCondition overlapsCondition) {
// constFlag.set(false);
// }
// /**
// * 用于处理 SafeCastExpression 类型的表达式。
// * @param safeCastExpression
// */
// @Override
// public void visit(SafeCastExpression safeCastExpression) {
// constFlag.set(false);
// }
@Override
public void visit(EqualsTo expr) {
visitBinaryExpression(expr);

View File

@@ -0,0 +1,16 @@
package org.jeecg.config.shiro;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 免认证注解认证系统结合spring MVC的@RequestMapping获取请求路径进行免登录配置
* @author eightmonth@qq.com
* @date 2024/2/28 9:58
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreAuth {
}

View File

@@ -1,5 +1,6 @@
package org.jeecg.config.shiro;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
@@ -17,19 +18,25 @@ import org.jeecg.config.shiro.filters.CustomShiroFilterFactoryBean;
import org.jeecg.config.shiro.filters.JwtFilter;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.*;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.Environment;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.filter.DelegatingFilterProxy;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import jakarta.annotation.Resource;
import jakarta.servlet.Filter;
import jakarta.servlet.DispatcherType;
import java.lang.reflect.Method;
import java.util.*;
/**
@@ -40,6 +47,8 @@ import java.util.*;
@Slf4j
@Configuration
// 免认证注解 @IgnoreAuth 注解生效范围配置
@ComponentScan(basePackages = {"org.jeecg"})
public class ShiroConfig {
@Resource
@@ -50,7 +59,6 @@ public class ShiroConfig {
private JeecgBaseConfig jeecgBaseConfig;
@Autowired(required = false)
private RedisProperties redisProperties;
/**
* Filter Chain定义说明
*
@@ -165,6 +173,16 @@ public class ShiroConfig {
// 企业微信证书排除
filterChainDefinitionMap.put("/WW_verify*", "anon");
// 通过注解免登录url
List<String> ignoreAuthUrlList = collectIgnoreAuthUrl();
if (!CollectionUtils.isEmpty(ignoreAuthUrlList)) {
for (String url : ignoreAuthUrlList) {
filterChainDefinitionMap.put(url, "anon");
}
}
// 添加自己的过滤器并且取名为jwt
Map<String, Filter> filterMap = new HashMap<String, Filter>(1);
//如果cloudServer为空 则说明是单体 需要加载跨域配置【微服务跨域切换】
@@ -181,6 +199,20 @@ public class ShiroConfig {
return shiroFilterFactoryBean;
}
//update-begin---author:chenrui ---date:20240126 for【QQYUN-7932】AI助手------------
@Bean
public FilterRegistrationBean shiroFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new DelegatingFilterProxy("shiroFilterFactoryBean"));
registration.setEnabled(true);
registration.addUrlPatterns("/*");
//支持异步
registration.setAsyncSupported(true);
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC);
return registration;
}
//update-end---author:chenrui ---date:20240126 for【QQYUN-7932】AI助手------------
@Bean("securityManager")
public DefaultWebSecurityManager securityManager(ShiroRealm myRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
@@ -270,7 +302,7 @@ public class ShiroConfig {
return sentinelManager;
}
// redis 单机支持,在集群为空,或者集群无机器时候使用 add by jzyadmin@163.com
if (lettuceConnectionFactory.getClusterConfiguration() == null || lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().isEmpty()) {
RedisManager redisManager = new RedisManager();
@@ -303,4 +335,74 @@ public class ShiroConfig {
return manager;
}
@SneakyThrows
public List<String> collectIgnoreAuthUrl() {
List<String> ignoreAuthUrls = new ArrayList<>();
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new AnnotationTypeFilter(RestController.class));
// 获取当前类的扫描注解的配置
Set<BeanDefinition> components = new HashSet<>();
for (String basePackage : AnnotationUtils.getAnnotation(ShiroConfig.class, ComponentScan.class).basePackages()) {
components.addAll(provider.findCandidateComponents(basePackage));
}
// 逐个匹配获取免认证路径
for (BeanDefinition component : components) {
String beanClassName = component.getBeanClassName();
Class<?> clazz = Class.forName(beanClassName);
RequestMapping base = clazz.getAnnotation(RequestMapping.class);
String[] baseUrl = {};
if (Objects.nonNull(base)) {
baseUrl = base.value();
}
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(RequestMapping.class)) {
RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
String[] uri = requestMapping.value();
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(GetMapping.class)) {
GetMapping requestMapping = method.getAnnotation(GetMapping.class);
String[] uri = requestMapping.value();
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(PostMapping.class)) {
PostMapping requestMapping = method.getAnnotation(PostMapping.class);
String[] uri = requestMapping.value();
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(PutMapping.class)) {
PutMapping requestMapping = method.getAnnotation(PutMapping.class);
String[] uri = requestMapping.value();
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(DeleteMapping.class)) {
DeleteMapping requestMapping = method.getAnnotation(DeleteMapping.class);
String[] uri = requestMapping.value();
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(PatchMapping.class)) {
PatchMapping requestMapping = method.getAnnotation(PatchMapping.class);
String[] uri = requestMapping.value();
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
}
}
}
return ignoreAuthUrls;
}
private List<String> rebuildUrl(String[] bases, String[] uris) {
List<String> urls = new ArrayList<>();
for (String base : bases) {
for (String uri : uris) {
urls.add(prefix(base)+prefix(uri));
}
}
return urls;
}
private String prefix(String seg) {
return seg.startsWith("/") ? seg : "/"+seg;
}
}

View File

@@ -62,9 +62,11 @@ public class ShiroRealm extends AuthorizingRealm {
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
log.debug("===============Shiro权限认证开始============ [ roles、permissions]==========");
String username = null;
String userId = null;
if (principals != null) {
LoginUser sysUser = (LoginUser) principals.getPrimaryPrincipal();
username = sysUser.getUsername();
userId = sysUser.getId();
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
@@ -74,7 +76,7 @@ public class ShiroRealm extends AuthorizingRealm {
info.setRoles(roleSet);
// 设置用户拥有的权限集合比如“sys:role:add,sys:user:add”
Set<String> permissionSet = commonApi.queryUserAuths(username);
Set<String> permissionSet = commonApi.queryUserAuths(userId);
info.addStringPermissions(permissionSet);
//System.out.println(permissionSet);
log.info("===============Shiro权限认证成功==============");

View File

@@ -172,7 +172,11 @@ public class HttpUtils {
String[] params = param.split("&");
for (String s : params) {
int index = s.indexOf("=");
result.put(s.substring(0, index), s.substring(index + 1));
//update-begin---author:chenrui ---date:20240222 for[issues/5879]数据查询传ds=“”造成的异常------------
if (index != -1) {
result.put(s.substring(0, index), s.substring(index + 1));
}
//update-end---author:chenrui ---date:20240222 for[issues/5879]数据查询传ds=“”造成的异常------------
}
return result;
}
@@ -196,7 +200,11 @@ public class HttpUtils {
String[] params = param.split("&");
for (String s : params) {
int index = s.indexOf("=");
result.put(s.substring(0, index), s.substring(index + 1));
//update-begin---author:chenrui ---date:20240222 for[issues/5879]数据查询传ds=“”造成的异常------------
if (index != -1) {
result.put(s.substring(0, index), s.substring(index + 1));
}
//update-end---author:chenrui ---date:20240222 for[issues/5879]数据查询传ds=“”造成的异常------------
}
return result;
}