JeecgBoot低代码平台 3.0版本发布—新里程牌开始,迎接VUE3版本到来!!

This commit is contained in:
zhangdaiscott
2021-10-27 10:28:14 +08:00
parent 9760185bf6
commit 0acea1abff
124 changed files with 5049 additions and 241273 deletions

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-base-api</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -8,10 +8,10 @@ import java.util.SortedMap;
import javax.servlet.http.HttpServletRequest;
import org.jeecg.common.config.mqtoken.UserTokenContext;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.PathMatcherUtil;
import org.jeecg.common.config.mqtoken.UserTokenContext;
import org.jeecg.config.sign.interceptor.SignAuthConfiguration;
import org.jeecg.config.sign.util.HttpUtils;
import org.jeecg.config.sign.util.SignUtil;

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-base-api</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-base</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-base</artifactId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -114,7 +114,7 @@
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>hibernate-re</artifactId>
<version>2.4.6-beta1</version>
<version>3.0.0-beta</version>
</dependency>
<!-- 数据库驱动 -->

View File

@ -1,24 +0,0 @@
package org.jeecg.common.api;
import org.jeecg.common.api.vo.OaWpsModel;
/**
* @Description: WPS通用接口
* @Author: wangshuai
* @Date:20200709
* @Version:V1.0
*/
public interface IWpsBaseAPI {
/*根据模板id获取模板信息*/
OaWpsModel getById(String id);
/*根据文件路径下载文件*/
void downloadOosFiles(String objectName, String basePath,String fileName);
/*WPS 设置数据存储,用于逻辑判断*/
void context(String type,String text);
/*删除WPS模板相关信息*/
void deleteById(String id);
}

View File

@ -1,47 +0,0 @@
package org.jeecg.common.api.desform;
import org.jeecg.common.system.vo.DictModel;
import java.util.List;
import java.util.Map;
/**
* 表单设计器【System】翻译API接口
*
* @author sunjianlei
*/
public interface ISysTranslateAPI {
/**
* 查询分类字典翻译
*/
List<String> categoryLoadDictItem(String ids);
/**
* 根据字典code加载字典text
*
* @param dictCode 顺序tableName,text,code
* @param keys 要查询的key
* @return
*/
List<String> dictLoadDictItem(String dictCode, String keys);
/**
* 获取字典数据
*
* @param dictCode 顺序tableName,text,code
* @param dictCode 要查询的key
* @return
*/
List<DictModel> dictGetDictItems(String dictCode);
/**
* 【JSearchSelectTag下拉搜索组件专用接口】
* 大数据量的字典表 走异步加载 即前端输入内容过滤数据
*
* @param dictCode 字典code格式table,text,code
* @return
*/
List<DictModel> dictLoadDict(String dictCode, String keyword, Integer pageSize);
}

View File

@ -1,107 +0,0 @@
package org.jeecg.common.api.vo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* @Description: 文档
* @Author: jeecg-boot
* @Date: 2020-06-09
* @Version: V1.0
*/
@Data
@TableName("oa_wps_file")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "oa_wps_file对象", description = "文档")
public class OaWpsModel implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "id")
private String id;
/**
* name
*/
@Excel(name = "name", width = 15)
@ApiModelProperty(value = "name")
private String name;
/**
* version
*/
@Excel(name = "version", width = 15)
@ApiModelProperty(value = "version")
private Integer version;
/**
* size
*/
@Excel(name = "size", width = 15)
@ApiModelProperty(value = "size")
private Integer size;
/**
* downloadUrl
*/
@Excel(name = "downloadUrl", width = 15)
@ApiModelProperty(value = "downloadUrl")
private String downloadUrl;
/**
* deleted
*/
@Excel(name = "deleted", width = 15)
@ApiModelProperty(value = "deleted")
private String deleted;
/**
* canDelete
*/
@Excel(name = "canDelete", width = 15)
@ApiModelProperty(value = "canDelete")
private String canDelete;
/**
* 创建人
*/
@ApiModelProperty(value = "创建人")
private String createBy;
/**
* 创建时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@ApiModelProperty(value = "创建时间")
private Date createTime;
/**
* 更新人
*/
@ApiModelProperty(value = "更新人")
private String updateBy;
/**
* 更新时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@ApiModelProperty(value = "更新时间")
private Date updateTime;
/**
* 组织机构编码
*/
@ApiModelProperty(value = "组织机构编码")
private String sysOrgCode;
@TableField(exist = false)
private String userId;
}

View File

@ -30,7 +30,7 @@ public class Result<T> implements Serializable {
* 返回处理消息
*/
@ApiModelProperty(value = "返回处理消息")
private String message = "操作成功!";
private String message = "";
/**
* 返回代码
@ -51,7 +51,16 @@ public class Result<T> implements Serializable {
private long timestamp = System.currentTimeMillis();
public Result() {
}
/**
* 兼容VUE3版token失效不跳转登录页面
* @param code
* @param message
*/
public Result(Integer code,String message) {
this.code = code;
this.message = message;
}
public Result<T> success(String message) {
@ -66,7 +75,6 @@ public class Result<T> implements Serializable {
Result<Object> r = new Result<Object>();
r.setSuccess(true);
r.setCode(CommonConstant.SC_OK_200);
r.setMessage("成功");
return r;
}
@ -92,7 +100,6 @@ public class Result<T> implements Serializable {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(CommonConstant.SC_OK_200);
r.setMessage("成功");
return r;
}

View File

@ -25,6 +25,7 @@ import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@ -261,7 +262,10 @@ public class DictAspect {
for (DictModel dict : texts) {
String redisKey = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, dict.getValue());
try {
redisTemplate.opsForValue().set(redisKey, dict.getText());
// update-begin-author:taoyan date:20211012 for: 字典表翻译注解缓存未更新 issues/3061
// 保留5分钟
redisTemplate.opsForValue().set(redisKey, dict.getText(), 300, TimeUnit.SECONDS);
// update-end-author:taoyan date:20211012 for: 字典表翻译注解缓存未更新 issues/3061
} catch (Exception e) {
log.warn(e.getMessage(), e);
}

View File

@ -292,6 +292,7 @@ public interface CommonConstant {
public final static String X_ACCESS_TOKEN = "X-Access-Token";
public final static String X_SIGN = "X-Sign";
public final static String X_TIMESTAMP = "X-TIMESTAMP";
public final static String TOKEN_IS_INVALID_MSG = "Token失效请重新登录!";
/**
* 多租户 请求头

View File

@ -10,6 +10,8 @@ public interface DataBaseConstant {
public static final String DB_TYPE_POSTGRESQL = "POSTGRESQL";
public static final String DB_TYPE_SQLSERVER = "SQLSERVER";
public static final String DB_TYPE_MARIADB = "MARIADB";
public static final String DB_TYPE_DB2 = "DB2";
public static final String DB_TYPE_HSQL = "HSQL";
// // 数据库类型,对应 database_type 字典
// public static final String DB_TYPE_MYSQL_NUM = "1";

View File

@ -0,0 +1,19 @@
package org.jeecg.common.exception;
public class JeecgBoot401Exception extends RuntimeException {
private static final long serialVersionUID = 1L;
public JeecgBoot401Exception(String message){
super(message);
}
public JeecgBoot401Exception(Throwable cause)
{
super(cause);
}
public JeecgBoot401Exception(String message, Throwable cause)
{
super(message,cause);
}
}

View File

@ -7,8 +7,10 @@ import org.jeecg.common.api.vo.Result;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.connection.PoolException;
import org.springframework.http.HttpStatus;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.NoHandlerFoundException;
@ -29,11 +31,21 @@ public class JeecgBootExceptionHandler {
* 处理自定义异常
*/
@ExceptionHandler(JeecgBootException.class)
public Result<?> handleRRException(JeecgBootException e){
public Result<?> handleJeecgBootException(JeecgBootException e){
log.error(e.getMessage(), e);
return Result.error(e.getMessage());
}
/**
* 处理自定义异常
*/
@ExceptionHandler(JeecgBoot401Exception.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public Result<?> handleJeecgBoot401Exception(JeecgBoot401Exception e){
log.error(e.getMessage(), e);
return new Result(401,e.getMessage());
}
@ExceptionHandler(NoHandlerFoundException.class)
public Result<?> handlerNoFoundException(Exception e) {
log.error(e.getMessage(), e);

View File

@ -37,8 +37,9 @@ import java.util.stream.Collectors;
*/
@Slf4j
public class JeecgController<T, S extends IService<T>> {
//issues/2933 JeecgController注入service时改用protected修饰能避免重复引用service
@Autowired
S service;
protected S service;
@Value("${jeecg.path.upload}")
private String upLoadPath;

View File

@ -99,7 +99,7 @@ public class QueryGenerator {
* <br>正确示例:QueryWrapper<JeecgDemo> queryWrapper = new QueryWrapper<JeecgDemo>();
* <br>3.也可以不使用这个方法直接调用 {@link #initQueryWrapper}直接获取实例
*/
public static void installMplus(QueryWrapper<?> queryWrapper,Object searchObj,Map<String, String[]> parameterMap) {
private static void installMplus(QueryWrapper<?> queryWrapper,Object searchObj,Map<String, String[]> parameterMap) {
/*
* 注意:权限查询由前端配置数据规则 当一个人有多个所属部门时候 可以在规则配置包含条件 orgCode 包含 #{sys_org_code}
@ -216,7 +216,7 @@ public class QueryGenerator {
}
//多字段排序 TODO 需要修改前端
public static void doMultiFieldsOrder(QueryWrapper<?> queryWrapper,Map<String, String[]> parameterMap) {
private static void doMultiFieldsOrder(QueryWrapper<?> queryWrapper,Map<String, String[]> parameterMap) {
String column=null,order=null;
if(parameterMap!=null&& parameterMap.containsKey(ORDER_COLUMN)) {
column = parameterMap.get(ORDER_COLUMN)[0];
@ -258,7 +258,7 @@ public class QueryGenerator {
* @param parameterMap 参数对象
* @param fieldColumnMap 实体字段和数据库列对应的map
*/
public static void doSuperQuery(QueryWrapper<?> queryWrapper,Map<String, String[]> parameterMap, Map<String,String> fieldColumnMap) {
private static void doSuperQuery(QueryWrapper<?> queryWrapper,Map<String, String[]> parameterMap, Map<String,String> fieldColumnMap) {
if(parameterMap!=null&& parameterMap.containsKey(SUPER_QUERY_PARAMS)){
String superQueryParams = parameterMap.get(SUPER_QUERY_PARAMS)[0];
String superQueryMatchType = parameterMap.get(SUPER_QUERY_MATCH_TYPE) != null ? parameterMap.get(SUPER_QUERY_MATCH_TYPE)[0] : MatchTypeEnum.AND.getValue();
@ -347,7 +347,7 @@ public class QueryGenerator {
* @param value
* @return
*/
private static QueryRuleEnum convert2Rule(Object value) {
public static QueryRuleEnum convert2Rule(Object value) {
// 避免空数据
// update-begin-author:taoyan date:20210629 for: 查询条件输入空格导致return null后续判断导致抛出null异常
if (value == null) {
@ -595,7 +595,7 @@ public class QueryGenerator {
/**
* 获取请求对应的数据权限规则
* 获取请求对应的数据权限规则 TODO 相同列权限多个 有问题
* @return
*/
public static Map<String, SysPermissionDataRuleModel> getRuleMap() {
@ -615,30 +615,6 @@ public class QueryGenerator {
}
return ruleMap;
}
/**
* 获取请求对应的数据权限规则
* @return
*/
public static Map<String, SysPermissionDataRuleModel> getRuleMap(List<SysPermissionDataRuleModel> list) {
Map<String, SysPermissionDataRuleModel> ruleMap = new HashMap<String, SysPermissionDataRuleModel>();
if(list==null){
list =JeecgDataAutorUtils.loadDataSearchConditon();
}
if(list != null&&list.size()>0){
if(list.get(0)==null){
return ruleMap;
}
for (SysPermissionDataRuleModel rule : list) {
String column = rule.getRuleColumn();
if(QueryRuleEnum.SQL_RULES.getValue().equals(rule.getRuleConditions())) {
column = SQL_RULES_COLUMN+rule.getId();
}
ruleMap.put(column, rule);
}
}
return ruleMap;
}
private static void addRuleToQueryWrapper(SysPermissionDataRuleModel dataRule, String name, Class propertyType, QueryWrapper<?> queryWrapper) {
QueryRuleEnum rule = QueryRuleEnum.getByValue(dataRule.getRuleConditions());
@ -761,7 +737,7 @@ public class QueryGenerator {
* @param dataBaseType
* @return
*/
public static String getSingleSqlByRule(QueryRuleEnum rule,String field,Object value,boolean isString, String dataBaseType) {
private static String getSingleSqlByRule(QueryRuleEnum rule,String field,Object value,boolean isString, String dataBaseType) {
String res = "";
switch (rule) {
case GT:
@ -813,7 +789,7 @@ public class QueryGenerator {
* @param isString
* @return
*/
public static String getSingleSqlByRule(QueryRuleEnum rule,String field,Object value,boolean isString) {
private static String getSingleSqlByRule(QueryRuleEnum rule,String field,Object value,boolean isString) {
return getSingleSqlByRule(rule, field, value, isString, null);
}

View File

@ -5,13 +5,19 @@ import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Joiner;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.DataBaseConstant;
import org.jeecg.common.exception.JeecgBootException;
@ -31,6 +37,28 @@ public class JwtUtil {
// Token过期时间30分钟用户登录过期时间是此时间的两倍以token在reids缓存时间为准
public static final long EXPIRE_TIME = 30 * 60 * 1000;
/**
*
* @param response
* @param code
* @param errorMsg
*/
public static void responseError(ServletResponse response, Integer code, String errorMsg) {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
Result jsonResult = new Result(code, errorMsg);
OutputStream os = null;
try {
os = httpServletResponse.getOutputStream();
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setStatus(401);
os.write(new ObjectMapper().writeValueAsString(jsonResult).getBytes("UTF-8"));
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 校验token是否正确
*

View File

@ -1,26 +1,30 @@
package org.jeecg.common.util;
import java.io.*;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.sql.DataSource;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.DataBaseConstant;
import org.jeecg.common.util.filter.FileTypeFilter;
import org.jeecg.common.util.oss.OssBootUtil;
import org.jeecgframework.poi.util.PoiPublicUtil;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;
import lombok.extern.slf4j.Slf4j;
import javax.sql.DataSource;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Slf4j
public class CommonUtils {
@ -207,6 +211,42 @@ public class CommonUtils {
}
}
/**
* 根据数据源key获取DataSourceProperty
* @param sourceKey
* @return
*/
public static DataSourceProperty getDataSourceProperty(String sourceKey){
DynamicDataSourceProperties prop = SpringContextUtils.getApplicationContext().getBean(DynamicDataSourceProperties.class);
Map<String, DataSourceProperty> map = prop.getDatasource();
DataSourceProperty db = (DataSourceProperty)map.get(sourceKey);
return db;
}
/**
* 根据sourceKey 获取数据源连接
* @param sourceKey
* @return
* @throws SQLException
*/
public static Connection getDataSourceConnect(String sourceKey) throws SQLException {
if (oConvertUtils.isEmpty(sourceKey)) {
sourceKey = "master";
}
DynamicDataSourceProperties prop = SpringContextUtils.getApplicationContext().getBean(DynamicDataSourceProperties.class);
Map<String, DataSourceProperty> map = prop.getDatasource();
DataSourceProperty db = (DataSourceProperty)map.get(sourceKey);
if(db==null){
return null;
}
DriverManagerDataSource ds = new DriverManagerDataSource ();
ds.setDriverClassName(db.getDriverClassName());
ds.setUrl(db.getUrl());
ds.setUsername(db.getUsername());
ds.setPassword(db.getPassword());
return ds.getConnection();
}
/**
* 获取数据库类型
* @param dataSource

View File

@ -38,7 +38,7 @@ public class ImportExcelUtil {
}
}
public static List<String> importDateSave(List<Object> list, Class serviceClass,List<String> errorMessage,String errorFlag) {
public static List<String> importDateSave(List<?> list, Class serviceClass, List<String> errorMessage, String errorFlag) {
IService bean =(IService) SpringContextUtils.getBean(serviceClass);
for (int i = 0; i < list.size(); i++) {
try {

View File

@ -1,6 +1,7 @@
package org.jeecg.common.util;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.constant.ServiceNameConstants;
import org.springframework.beans.BeansException;
@ -38,6 +39,12 @@ public class SpringContextUtils implements ApplicationContextAware {
public static HttpServletRequest getHttpServletRequest() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
/**
* 获取HttpServletResponse
*/
public static HttpServletResponse getHttpServletResponse() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
}
/**
* 获取项目根路径 basePath

View File

@ -2,9 +2,9 @@ package org.jeecg.common.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBoot401Exception;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
@ -40,27 +40,57 @@ public class TokenUtils {
String token = getTokenByRequest(request);
if (StringUtils.isBlank(token)) {
throw new AuthenticationException("Token不能为空!");
throw new JeecgBoot401Exception("Token不能为空!");
}
// 解密获得username用于和数据库进行对比
String username = JwtUtil.getUsername(token);
if (username == null) {
throw new AuthenticationException("Token非法无效!");
throw new JeecgBoot401Exception("Token非法无效!");
}
// 查询用户信息
LoginUser user = commonAPI.getUserByName(username);
if (user == null) {
throw new AuthenticationException("用户不存在!");
throw new JeecgBoot401Exception("用户不存在!");
}
// 判断用户状态
if (user.getStatus() != 1) {
throw new AuthenticationException("账号已锁定,请联系管理员!");
throw new JeecgBoot401Exception("账号已锁定,请联系管理员!");
}
// 校验token是否超时失效 & 或者账号密码是否错误
if (!jwtTokenRefresh(token, username, user.getPassword(), redisUtil)) {
throw new AuthenticationException("Token失效请重新登录");
throw new JeecgBoot401Exception("Token失效请重新登录");
}
return true;
}
/**
* 验证Token
*/
public static boolean verifyToken(String token, CommonAPI commonAPI, RedisUtil redisUtil) {
if (StringUtils.isBlank(token)) {
throw new JeecgBoot401Exception("token不能为空!");
}
// 解密获得username用于和数据库进行对比
String username = JwtUtil.getUsername(token);
if (username == null) {
throw new JeecgBoot401Exception("token非法无效!");
}
// 查询用户信息
LoginUser user = commonAPI.getUserByName(username);
if (user == null) {
throw new JeecgBoot401Exception("用户不存在!");
}
// 判断用户状态
if (user.getStatus() != 1) {
throw new JeecgBoot401Exception("账号已被锁定,请联系管理员!");
}
// 校验token是否超时失效 & 或者账号密码是否错误
if (!jwtTokenRefresh(token, username, user.getPassword(), redisUtil)) {
throw new JeecgBoot401Exception(CommonConstant.TOKEN_IS_INVALID_MSG);
}
return true;
}
@ -95,34 +125,4 @@ public class TokenUtils {
return false;
}
/**
* 验证Token
*/
public static boolean verifyToken(String token, CommonAPI commonAPI, RedisUtil redisUtil) {
if (StringUtils.isBlank(token)) {
throw new AuthenticationException("token不能为空!");
}
// 解密获得username用于和数据库进行对比
String username = JwtUtil.getUsername(token);
if (username == null) {
throw new AuthenticationException("token非法无效!");
}
// 查询用户信息
LoginUser user = commonAPI.getUserByName(username);
if (user == null) {
throw new AuthenticationException("用户不存在!");
}
// 判断用户状态
if (user.getStatus() != 1) {
throw new AuthenticationException("账号已被锁定,请联系管理员!");
}
// 校验token是否超时失效 & 或者账号密码是否错误
if (!jwtTokenRefresh(token, username, user.getPassword(), redisUtil)) {
throw new AuthenticationException("Token失效请重新登录!");
}
return true;
}
}

View File

@ -1,6 +1,10 @@
package org.jeecg.common.util.dynamic.db;
import com.baomidou.mybatisplus.annotation.DbType;
import org.jeecg.common.constant.DataBaseConstant;
import java.util.HashMap;
import java.util.Map;
/**
* 数据库类型判断
@ -8,6 +12,34 @@ import com.baomidou.mybatisplus.annotation.DbType;
*/
public class DbTypeUtils {
public static Map<String, String> dialectMap = new HashMap<String, String>();
static{
dialectMap.put("mysql", "org.hibernate.dialect.MySQL5InnoDBDialect");
dialectMap.put("mariadb", "org.hibernate.dialect.MariaDBDialect");// 1 --
dialectMap.put("oracle", "org.hibernate.dialect.OracleDialect");//1
dialectMap.put("oracle12c", "org.hibernate.dialect.OracleDialect"); // TODO 没找到不确定
dialectMap.put("db2", "org.hibernate.dialect.DB2390Dialect"); // 1xx
dialectMap.put("h2", "org.hibernate.dialect.HSQLDialect");// H2数据库
dialectMap.put("hsql", "org.hibernate.dialect.HSQLDialect");// HSQL数据库 1
dialectMap.put("sqlite", "org.jeecg.modules.online.config.dialect.SQLiteDialect"); //SQLite数据库 应用平台mobile
dialectMap.put("postgresql", "org.hibernate.dialect.PostgreSQLDialect"); //1 --
dialectMap.put("sqlserver2005", "org.hibernate.dialect.SQLServer2005Dialect");
dialectMap.put("sqlserver", "org.hibernate.dialect.SQLServerDialect"); //1
dialectMap.put("dm", "org.hibernate.dialect.OracleDialect");//达梦数据库 [国产] 1--
dialectMap.put("xugu", "org.hibernate.dialect.HSQLDialect"); //虚谷数据库
dialectMap.put("kingbasees", "org.hibernate.dialect.PostgreSQLDialect"); //人大金仓 [国产] 1
dialectMap.put("phoenix", "org.hibernate.dialect.HSQLDialect"); // Phoenix HBase数据库
dialectMap.put("zenith", "org.hibernate.dialect.PostgreSQLDialect"); // Gauss 数据库
dialectMap.put("clickhouse", "org.hibernate.dialect.MySQLDialect"); //阿里云PolarDB
dialectMap.put("gbase", "org.hibernate.dialect.PostgreSQLDialect"); // 南大通用数据库 TODO 没找到不确定
dialectMap.put("oscar", "org.hibernate.dialect.PostgreSQLDialect"); //神通数据库 [国产] TODO 没找到不确定
dialectMap.put("sybase", "org.hibernate.dialect.SybaseDialect"); //Sybase ASE 数据库
dialectMap.put("oceanbase", "org.hibernate.dialect.PostgreSQLDialect"); //OceanBase 数据库 TODO 没找到不确定
dialectMap.put("Firebird", "org.hibernate.dialect.FirebirdDialect");
dialectMap.put("highgo", "org.hibernate.dialect.HSQLDialect"); //瀚高数据库
dialectMap.put("other", "org.hibernate.dialect.PostgreSQLDialect");
}
public static boolean dbTypeIsMySQL(DbType dbType) {
return dbTypeIf(dbType, DbType.MYSQL, DbType.MARIADB, DbType.CLICK_HOUSE, DbType.SQLITE);
}
@ -24,6 +56,37 @@ public class DbTypeUtils {
return dbTypeIf(dbType, DbType.POSTGRE_SQL, DbType.KINGBASE_ES, DbType.GAUSS);
}
/**
* 根据枚举类 获取数据库类型的字符串
* @param dbType
* @return
*/
public static String getDbTypeString(DbType dbType){
if(DbType.DB2.equals(dbType)){
return DataBaseConstant.DB_TYPE_DB2;
}else if(DbType.HSQL.equals(dbType)){
return DataBaseConstant.DB_TYPE_HSQL;
}else if(dbTypeIsOracle(dbType)){
return DataBaseConstant.DB_TYPE_ORACLE;
}else if(dbTypeIsSQLServer(dbType)){
return DataBaseConstant.DB_TYPE_SQLSERVER;
}else if(dbTypeIsPostgre(dbType)){
return DataBaseConstant.DB_TYPE_POSTGRESQL;
}
return DataBaseConstant.DB_TYPE_MYSQL;
}
/**
* 根据枚举类 获取数据库方言字符串
* @param dbType
* @return
*/
public static String getDbDialect(DbType dbType){
return dialectMap.get(dbType.getDb());
}
/**
* 判断数据库类型
*/

View File

@ -111,6 +111,16 @@ public class DynamicDBUtil {
return new JdbcTemplate(dataSource);
}
/**
* 根据数据源获取NamedParameterJdbcTemplate
* @param dbKey
* @return
*/
private static NamedParameterJdbcTemplate getNamedParameterJdbcTemplate(String dbKey) {
DruidDataSource dataSource = getDbSourceByDbKey(dbKey);
return new NamedParameterJdbcTemplate(dataSource);
}
/**
* Executes the SQL statement in this <code>PreparedStatement</code> object,
* which must be an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or
@ -221,6 +231,31 @@ public class DynamicDBUtil {
return list;
}
/**
* 查询数量
* @param dbKey
* @param sql
* @param param
* @return
*/
public static Map<String, Object> queryCount(String dbKey, String sql, Map<String, Object> param){
NamedParameterJdbcTemplate npJdbcTemplate = getNamedParameterJdbcTemplate(dbKey);
return npJdbcTemplate.queryForMap(sql, param);
}
/**
* 查询列表数据
* @param dbKey
* @param sql
* @param param
* @return
*/
public static List<Map<String, Object>> findListByNamedParam(final String dbKey, String sql, Map<String, Object> param) {
NamedParameterJdbcTemplate npJdbcTemplate = getNamedParameterJdbcTemplate(dbKey);
List<Map<String, Object>> list = npJdbcTemplate.queryForList(sql, param);
return list;
}
/**
* 支持miniDao语法操作的查询
*

View File

@ -0,0 +1,25 @@
package org.jeecg.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 加载项目配置
*/
@Component("jeeccgBaseConfig")
@ConfigurationProperties(prefix = "jeecg")
public class JeeccgBaseConfig {
/**
* 是否启用安全模式
*/
private Boolean safeMode = false;
public Boolean getSafeMode() {
return safeMode;
}
public void setSafeMode(Boolean safeMode) {
this.safeMode = safeMode;
}
}

View File

@ -35,6 +35,11 @@ public class MybatisPlusSaasConfig {
static {
tenantTable.add("demo");
// //角色、菜单、部门
// tenantTable.add("sys_role");
// tenantTable.add("sys_permission");
// tenantTable.add("sys_depart");
}

View File

@ -118,8 +118,12 @@ public class ShiroConfig {
filterChainDefinitionMap.put("/jmreport/**", "anon");
filterChainDefinitionMap.put("/**/*.js.map", "anon");
filterChainDefinitionMap.put("/**/*.css.map", "anon");
//大屏模板例子
filterChainDefinitionMap.put("/test/bigScreen/**", "anon");
//测试示例
filterChainDefinitionMap.put("/test/bigScreen/**", "anon"); //大屏模板例子
//filterChainDefinitionMap.put("/test/jeecgDemo/rabbitMqClientTest/**", "anon"); //MQ测试
//filterChainDefinitionMap.put("/test/jeecgDemo/html", "anon"); //模板页面
//filterChainDefinitionMap.put("/test/jeecgDemo/redis/**", "anon"); //redis测试
//websocket排除
filterChainDefinitionMap.put("/websocket/**", "anon");//系统通知和公告

View File

@ -1,6 +1,5 @@
package org.jeecg.config.shiro;
import cn.hutool.crypto.SecureUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
@ -11,7 +10,6 @@ import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
@ -97,7 +95,14 @@ public class ShiroRealm extends AuthorizingRealm {
throw new AuthenticationException("token为空!");
}
// 校验token有效性
LoginUser loginUser = this.checkUserTokenIsEffect(token);
LoginUser loginUser = null;
try {
loginUser = this.checkUserTokenIsEffect(token);
} catch (AuthenticationException e) {
JwtUtil.responseError(SpringContextUtils.getHttpServletResponse(),401,e.getMessage());
e.printStackTrace();
return null;
}
return new SimpleAuthenticationInfo(loginUser, token, getName());
}
@ -125,7 +130,7 @@ public class ShiroRealm extends AuthorizingRealm {
}
// 校验token是否超时失效 & 或者账号密码是否错误
if (!jwtTokenRefresh(token, username, loginUser.getPassword())) {
throw new AuthenticationException("Token失效请重新登录!");
throw new AuthenticationException(CommonConstant.TOKEN_IS_INVALID_MSG);
}
//update-begin-author:taoyan date:20210609 for:校验用户的tenant_id和前端传过来的是否一致
String userTenantIds = loginUser.getRelTenantIds();

View File

@ -1,9 +1,9 @@
package org.jeecg.config.shiro.filters;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.mybatis.TenantContext;
import org.jeecg.config.shiro.JwtToken;
@ -48,7 +48,9 @@ public class JwtFilter extends BasicHttpAuthenticationFilter {
executeLogin(request, response);
return true;
} catch (Exception e) {
throw new AuthenticationException("Token失效请重新登录", e);
JwtUtil.responseError(response,401,CommonConstant.TOKEN_IS_INVALID_MSG);
return false;
//throw new AuthenticationException("Token失效请重新登录", e);
}
}

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-base</artifactId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<description>公共模块</description>

View File

@ -1,8 +1,9 @@
package org.jeecg.common.config.mqtoken;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* 存放token到上下文供队列调用feign使用

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-parent</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>