Browse Source

feat:新增小程序登录 shiro 校验

master
tanzhisong 2 months ago
parent
commit
918a37af17
18 changed files with 399 additions and 116 deletions
  1. +10
    -2
      jeecg-boot-base-core/src/main/java/org/jeecg/common/api/CommonAPI.java
  2. +34
    -6
      jeecg-boot-base-core/src/main/java/org/jeecg/common/system/util/JwtUtil.java
  3. +59
    -0
      jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/MLoginUser.java
  4. +29
    -2
      jeecg-boot-base-core/src/main/java/org/jeecg/common/util/TokenUtils.java
  5. +63
    -13
      jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroRealm.java
  6. +1
    -0
      jeecg-module-miniapp/pom.xml
  7. +0
    -1
      jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/store/controller/StoreController.java
  8. +20
    -1
      jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/user/contoller/MUserController.java
  9. +4
    -1
      jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/user/service/UserService.java
  10. +41
    -6
      jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/user/service/impl/UserServiceImpl.java
  11. +16
    -10
      jeecg-module-system/jeecg-system-api/jeecg-system-cloud-api/src/main/java/org/jeecg/common/system/api/ISysBaseAPI.java
  12. +7
    -1
      jeecg-module-system/jeecg-system-api/jeecg-system-cloud-api/src/main/java/org/jeecg/common/system/api/fallback/SysBaseAPIFallback.java
  13. +13
    -0
      jeecg-module-system/jeecg-system-biz/pom.xml
  14. +19
    -19
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/LoginController.java
  15. +14
    -13
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/ISysUserService.java
  16. +41
    -18
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysBaseApiImpl.java
  17. +27
    -22
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysUserServiceImpl.java
  18. +1
    -1
      jeecg-module-system/jeecg-system-start/src/main/resources/logback-spring.xml

+ 10
- 2
jeecg-boot-base-core/src/main/java/org/jeecg/common/api/CommonAPI.java View File

@ -18,7 +18,7 @@ public interface CommonAPI {
* @return * @return
*/ */
Set<String> queryUserRoles(String username); Set<String> queryUserRoles(String username);
/** /**
* 1查询用户角色信息 * 1查询用户角色信息
* @param userId * @param userId
@ -56,7 +56,15 @@ public interface CommonAPI {
* @return * @return
*/ */
public LoginUser getUserByName(String username); public LoginUser getUserByName(String username);
/**
* 5根据用户账号查询用户信息微信小程序
* @param username
* @return
*/
public MLoginUser getMUserByName(String username);
/** /**
* 5根据用户账号查询用户Id * 5根据用户账号查询用户Id
* @param username * @param username


+ 34
- 6
jeecg-boot-base-core/src/main/java/org/jeecg/common/system/util/JwtUtil.java View File

@ -103,6 +103,21 @@ public class JwtUtil {
} }
} }
/**
* 获得token中的信息无需secret解密也能获得
*
* @return token中包含的渠道
*/
public static String getChannel(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("channel").asString();
} catch (JWTDecodeException e) {
log.warn(e.getMessage(), e);
return null;
}
}
/** /**
* 生成签名,5min后过期 * 生成签名,5min后过期
* *
@ -115,12 +130,25 @@ public class JwtUtil {
Algorithm algorithm = Algorithm.HMAC256(secret); Algorithm algorithm = Algorithm.HMAC256(secret);
// 附带username信息 // 附带username信息
return JWT.create().withClaim("username", username).withExpiresAt(date).sign(algorithm); return JWT.create().withClaim("username", username).withExpiresAt(date).sign(algorithm);
}
/**
* 生成小程序签名,5min后过期
*
* @param username 用户名
* @param secret 用户的密码
* @return 加密的token
*/
public static String signMiniApp(String username, String secret) {
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
Algorithm algorithm = Algorithm.HMAC256(secret);
// 附带username信息
return JWT.create().withClaim("username", username).withClaim("channel","miniapp").withExpiresAt(date).sign(algorithm);
} }
/** /**
* 根据request中的token获取用户账号 * 根据request中的token获取用户账号
*
*
* @param request * @param request
* @return * @return
* @throws JeecgBootException * @throws JeecgBootException
@ -133,7 +161,7 @@ public class JwtUtil {
} }
return username; return username;
} }
/** /**
* 从session中获取变量 * 从session中获取变量
* @param key * @param key
@ -160,7 +188,7 @@ public class JwtUtil {
if(returnValue!=null){returnValue = returnValue + moshi;} if(returnValue!=null){returnValue = returnValue + moshi;}
return returnValue; return returnValue;
} }
/** /**
* 从当前用户中获取变量 * 从当前用户中获取变量
* @param key * @param key
@ -222,7 +250,7 @@ public class JwtUtil {
if(sysUser==null && user==null){ if(sysUser==null && user==null){
return null; return null;
} }
//替换为系统登录用户帐号 //替换为系统登录用户帐号
if (key.equals(DataBaseConstant.SYS_USER_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_USER_CODE_TABLE)) { if (key.equals(DataBaseConstant.SYS_USER_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_USER_CODE_TABLE)) {
if(user==null) { if(user==null) {
@ -249,7 +277,7 @@ public class JwtUtil {
returnValue = user.getSysUserName(); returnValue = user.getSysUserName();
} }
} }
//替换为系统用户登录所使用的机构编码 //替换为系统用户登录所使用的机构编码
else if (key.equals(DataBaseConstant.SYS_ORG_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_ORG_CODE_TABLE)) { else if (key.equals(DataBaseConstant.SYS_ORG_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_ORG_CODE_TABLE)) {
if(user==null) { if(user==null) {
@ -314,7 +342,7 @@ public class JwtUtil {
if(returnValue!=null){returnValue = returnValue + moshi;} if(returnValue!=null){returnValue = returnValue + moshi;}
return returnValue; return returnValue;
} }
// public static void main(String[] args) { // public static void main(String[] args) {
// String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjUzMzY1MTMsInVzZXJuYW1lIjoiYWRtaW4ifQ.xjhud_tWCNYBOg_aRlMgOdlZoWFFKB_givNElHNw3X0"; // String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjUzMzY1MTMsInVzZXJuYW1lIjoiYWRtaW4ifQ.xjhud_tWCNYBOg_aRlMgOdlZoWFFKB_givNElHNw3X0";
// System.out.println(JwtUtil.getUsername(token)); // System.out.println(JwtUtil.getUsername(token));


+ 59
- 0
jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/MLoginUser.java View File

@ -0,0 +1,59 @@
package org.jeecg.common.system.vo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.jeecg.common.aspect.annotation.Dict;
import org.jeecg.common.desensitization.annotation.SensitiveField;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
/**
* @author Tanzs
* @date 2025/2/18 下午4:23
* @description
*/
@Data
public class MLoginUser {
private java.lang.Integer id;
/**用户名*/
private java.lang.String nickName;
/**头像*/
private java.lang.String avatar;
/**手机号*/
@SensitiveField
private java.lang.String phone;
/**小程序 openid*/
private java.lang.String openid;
/**小程序 unionid*/
private java.lang.String unionid;
/**密码*/
@SensitiveField
private java.lang.String password;
/**状态*/
private java.lang.Integer status;
/**邮箱*/
@SensitiveField
private java.lang.String email;
/**最后登录时间*/
private java.util.Date lastLoginAt;
/**最后登录 IP*/
private java.lang.String lastLoginIp;
/**密码盐值*/
@SensitiveField
private java.lang.String passwordSalt;
/**邀请人*/
private java.lang.Integer inviterId;
/**创建日期*/
private java.util.Date createTime;
/**更新人*/
private java.lang.String updateBy;
/**更新日期*/
private java.util.Date updateTime;
/**所属部门*/
private java.lang.String sysOrgCode;
}

+ 29
- 2
jeecg-boot-base-core/src/main/java/org/jeecg/common/util/TokenUtils.java View File

@ -10,6 +10,7 @@ import org.jeecg.common.desensitization.util.SensitiveInfoUtil;
import org.jeecg.common.exception.JeecgBoot401Exception; import org.jeecg.common.exception.JeecgBoot401Exception;
import org.jeecg.common.system.util.JwtUtil; import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.MLoginUser;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -31,14 +32,14 @@ public class TokenUtils {
if (request == null) { if (request == null) {
return null; return null;
} }
String token = request.getParameter("token"); String token = request.getParameter("token");
if (token == null) { if (token == null) {
token = request.getHeader("X-Access-Token"); token = request.getHeader("X-Access-Token");
} }
return token; return token;
} }
/** /**
* 获取 request 里传递的 token * 获取 request 里传递的 token
* @return * @return
@ -170,4 +171,30 @@ public class TokenUtils {
} }
return loginUser; return loginUser;
} }
/**
* 获取登录用户
*
* @param commonApi
* @param username
* @return
*/
public static MLoginUser getMLoginUser(String username, CommonAPI commonApi, RedisUtil redisUtil) {
MLoginUser mLoginUser = null;
String mloginUserKey = CacheConstant.SYS_USERS_CACHE + "::" + username;
//重要此处通过redis原生获取缓存用户是为了解决微服务下system服务挂了其他服务互调不通问题---
if (redisUtil.hasKey(mloginUserKey)) {
try {
mLoginUser = (MLoginUser) redisUtil.get(mloginUserKey);
//解密用户
SensitiveInfoUtil.handlerObject(mLoginUser, false);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} else {
// 查询用户信息
mLoginUser = commonApi.getMUserByName(username);
}
return mLoginUser;
}
} }

+ 63
- 13
jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroRealm.java View File

@ -1,5 +1,6 @@
package org.jeecg.config.shiro; package org.jeecg.config.shiro;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationInfo;
@ -15,6 +16,7 @@ import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.constant.CommonConstant; import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil; import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.MLoginUser;
import org.jeecg.common.util.RedisUtil; import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.SpringContextUtils; import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.common.util.TokenUtils; import org.jeecg.common.util.TokenUtils;
@ -101,16 +103,29 @@ public class ShiroRealm extends AuthorizingRealm {
log.info("————————身份认证失败——————————IP地址: "+ oConvertUtils.getIpAddrByRequest(req) +",URL:"+req.getRequestURI()); log.info("————————身份认证失败——————————IP地址: "+ oConvertUtils.getIpAddrByRequest(req) +",URL:"+req.getRequestURI());
throw new AuthenticationException("token为空!"); throw new AuthenticationException("token为空!");
} }
// 校验token有效性
LoginUser loginUser = null;
try {
loginUser = this.checkUserTokenIsEffect(token);
} catch (AuthenticationException e) {
JwtUtil.responseError(SpringContextUtils.getHttpServletResponse(),401,e.getMessage());
e.printStackTrace();
return null;
// 校验token有效性 小程序和后台单独判读
String channel = JwtUtil.getChannel(token);
if (StrUtil.isNotEmpty(channel) && "miniapp".equals(channel)){
MLoginUser mLoginUser = null;
try {
mLoginUser = this.checkMUserTokenIsEffect(token);
} catch (AuthenticationException e) {
JwtUtil.responseError(SpringContextUtils.getHttpServletResponse(),401,e.getMessage());
e.printStackTrace();
return null;
}
return new SimpleAuthenticationInfo(mLoginUser, token, getName());
}else {
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());
} }
return new SimpleAuthenticationInfo(loginUser, token, getName());
} }
/** /**
@ -137,7 +152,7 @@ public class ShiroRealm extends AuthorizingRealm {
throw new AuthenticationException("账号已被锁定,请联系管理员!"); throw new AuthenticationException("账号已被锁定,请联系管理员!");
} }
// 校验token是否超时失效 & 或者账号密码是否错误 // 校验token是否超时失效 & 或者账号密码是否错误
if (!jwtTokenRefresh(token, username, loginUser.getPassword())) {
if (!jwtTokenRefresh(token, username, loginUser.getPassword(),null)) {
throw new AuthenticationException(CommonConstant.TOKEN_IS_INVALID_MSG); throw new AuthenticationException(CommonConstant.TOKEN_IS_INVALID_MSG);
} }
//update-begin-author:taoyan date:20210609 for:校验用户的tenant_id和前端传过来的是否一致 //update-begin-author:taoyan date:20210609 for:校验用户的tenant_id和前端传过来的是否一致
@ -160,7 +175,7 @@ public class ShiroRealm extends AuthorizingRealm {
LoginUser loginUserFromDb = commonApi.getUserByName(username); LoginUser loginUserFromDb = commonApi.getUserByName(username);
if (oConvertUtils.isNotEmpty(loginUserFromDb.getRelTenantIds())) { if (oConvertUtils.isNotEmpty(loginUserFromDb.getRelTenantIds())) {
String[] newArray = loginUserFromDb.getRelTenantIds().split(","); String[] newArray = loginUserFromDb.getRelTenantIds().split(",");
if (oConvertUtils.isIn(contextTenantId, newArray)) {
if (oConvertUtils.isIn(contextTenantId, newArray)) {
isAuthorization = true; isAuthorization = true;
} }
} }
@ -181,6 +196,36 @@ public class ShiroRealm extends AuthorizingRealm {
return loginUser; return loginUser;
} }
/**
* 校验 小程序token的有效性
*
* @param token
*/
public MLoginUser checkMUserTokenIsEffect(String token) throws AuthenticationException {
// 解密获得username用于和数据库进行对比
String username = JwtUtil.getUsername(token);
if (username == null) {
throw new AuthenticationException("token非法无效!");
}
// 查询用户信息
log.debug("———校验token是否有效————checkUserTokenIsEffect——————— "+ token);
MLoginUser mLoginUser = TokenUtils.getMLoginUser(username, commonApi, redisUtil);
//LoginUser loginUser = commonApi.getUserByName(username);
if (mLoginUser == null) {
throw new AuthenticationException("用户不存在!");
}
// 判断用户状态
if (mLoginUser.getStatus() != 1) {
throw new AuthenticationException("账号已被锁定,请联系管理员!");
}
// 校验token是否超时失效 & 或者账号密码是否错误
if (!jwtTokenRefresh(token, username, mLoginUser.getPassword(),"miniapp")) {
throw new AuthenticationException(CommonConstant.TOKEN_IS_INVALID_MSG);
}
return mLoginUser;
}
/** /**
* JWTToken刷新生命周期 实现 用户在线操作不掉线功能 * JWTToken刷新生命周期 实现 用户在线操作不掉线功能
* 1登录成功后将用户的JWT生成的Token作为kv存储到cache缓存里面(这时候kv值一样)缓存有效期设置为Jwt有效时间的2倍 * 1登录成功后将用户的JWT生成的Token作为kv存储到cache缓存里面(这时候kv值一样)缓存有效期设置为Jwt有效时间的2倍
@ -194,12 +239,17 @@ public class ShiroRealm extends AuthorizingRealm {
* @param passWord * @param passWord
* @return * @return
*/ */
public boolean jwtTokenRefresh(String token, String userName, String passWord) {
public boolean jwtTokenRefresh(String token, String userName, String passWord, String channel) {
String cacheToken = String.valueOf(redisUtil.get(CommonConstant.PREFIX_USER_TOKEN + token)); String cacheToken = String.valueOf(redisUtil.get(CommonConstant.PREFIX_USER_TOKEN + token));
if (oConvertUtils.isNotEmpty(cacheToken)) { if (oConvertUtils.isNotEmpty(cacheToken)) {
// 校验token有效性 // 校验token有效性
if (!JwtUtil.verify(cacheToken, userName, passWord)) { if (!JwtUtil.verify(cacheToken, userName, passWord)) {
String newAuthorization = JwtUtil.sign(userName, passWord);
String newAuthorization = null;
if (StrUtil.isNotEmpty(channel)){
newAuthorization = JwtUtil.signMiniApp(userName, passWord);
}else {
newAuthorization= JwtUtil.sign(userName, passWord);
}
// 设置超时时间 // 设置超时时间
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, newAuthorization); redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, newAuthorization);
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME *2 / 1000); redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME *2 / 1000);


+ 1
- 0
jeecg-module-miniapp/pom.xml View File

@ -21,6 +21,7 @@
<artifactId>jeecg-module-demo</artifactId> <artifactId>jeecg-module-demo</artifactId>
<version>3.7.2</version> <version>3.7.2</version>
</dependency> </dependency>
<!--微信小程序封装依赖--> <!--微信小程序封装依赖-->
<dependency> <dependency>
<groupId>com.github.binarywang</groupId> <groupId>com.github.binarywang</groupId>


+ 0
- 1
jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/store/controller/StoreController.java View File

@ -43,7 +43,6 @@ public class StoreController extends JeecgController<AppStore, IAppStoreService>
//@AutoLog(value = "门店管理-分页列表查询") //@AutoLog(value = "门店管理-分页列表查询")
@ApiOperation(value="门店管理-列表查询", notes="门店管理-列表查询") @ApiOperation(value="门店管理-列表查询", notes="门店管理-列表查询")
@GetMapping(value = "/list") @GetMapping(value = "/list")
@IgnoreAuth
public Result<List<AppStore>> queryPageList(AppStore appStore, HttpServletRequest req) { public Result<List<AppStore>> queryPageList(AppStore appStore, HttpServletRequest req) {
// 自定义查询规则 // 自定义查询规则
Map<String, QueryRuleEnum> customeRuleMap = new HashMap<>(); Map<String, QueryRuleEnum> customeRuleMap = new HashMap<>();


+ 20
- 1
jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/user/contoller/MUserController.java View File

@ -4,6 +4,9 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result; import org.jeecg.common.api.vo.Result;
import org.jeecg.common.desensitization.util.SensitiveInfoUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.MLoginUser;
import org.jeecg.config.shiro.IgnoreAuth; import org.jeecg.config.shiro.IgnoreAuth;
import org.jeecg.modules.miniapp.user.domain.WxLoginInfo; import org.jeecg.modules.miniapp.user.domain.WxLoginInfo;
import org.jeecg.modules.miniapp.user.service.UserService; import org.jeecg.modules.miniapp.user.service.UserService;
@ -26,7 +29,6 @@ public class MUserController {
@Autowired @Autowired
UserService userService; UserService userService;
@IgnoreAuth @IgnoreAuth
@ApiOperation(value="微信小程序登录", notes="微信小程序登录测试") @ApiOperation(value="微信小程序登录", notes="微信小程序登录测试")
@PostMapping(value = "/wxlogin") @PostMapping(value = "/wxlogin")
@ -55,5 +57,22 @@ public class MUserController {
return userService.logout(request); return userService.logout(request);
} }
/**
* 根据用户账号查询用户信息
* @param username
* @return
*/
@GetMapping("/getUserByName")
public MLoginUser getUserByName(@RequestParam("username") String username){
MLoginUser mLoginUser = userService.getMUserByName(username);
//用户信息加密
try {
SensitiveInfoUtil.handlerObject(mLoginUser, true);
} catch (IllegalAccessException e) {
log.error(e.getMessage(), e);
}
return mLoginUser;
}
} }

+ 4
- 1
jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/user/service/UserService.java View File

@ -2,6 +2,7 @@ package org.jeecg.modules.miniapp.user.service;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import org.jeecg.common.api.vo.Result; import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.MLoginUser;
import org.jeecg.modules.sysMiniapp.appuser.entity.AppUser; import org.jeecg.modules.sysMiniapp.appuser.entity.AppUser;
import org.jeecg.modules.miniapp.user.domain.WxLoginInfo; import org.jeecg.modules.miniapp.user.domain.WxLoginInfo;
@ -38,7 +39,9 @@ public interface UserService {
* @param userName * @param userName
* @return * @return
*/ */
AppUser getUserByName(String userName);
MLoginUser getMUserByName(String userName);
MLoginUser getMEncodeUserInfo(String username);
Result<?> checkUserIsEffective(AppUser appUser); Result<?> checkUserIsEffective(AppUser appUser);
} }

+ 41
- 6
jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/user/service/impl/UserServiceImpl.java View File

@ -5,13 +5,17 @@ import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.shiro.SecurityUtils; import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result; import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CacheConstant; import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.constant.CommonConstant; import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.desensitization.annotation.SensitiveEncode;
import org.jeecg.common.desensitization.util.SensitiveInfoUtil;
import org.jeecg.common.system.util.JwtUtil; import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.MLoginUser;
import org.jeecg.common.util.IpUtils; import org.jeecg.common.util.IpUtils;
import org.jeecg.common.util.PasswordUtil; import org.jeecg.common.util.PasswordUtil;
import org.jeecg.common.util.RedisUtil; import org.jeecg.common.util.RedisUtil;
@ -22,6 +26,7 @@ import org.jeecg.modules.sysMiniapp.appuser.mapper.AppUserMapper;
import org.jeecg.modules.sysMiniapp.appuser.service.IAppUserService; import org.jeecg.modules.sysMiniapp.appuser.service.IAppUserService;
import org.jeecg.modules.miniapp.user.domain.WxLoginInfo; import org.jeecg.modules.miniapp.user.domain.WxLoginInfo;
import org.jeecg.modules.miniapp.user.service.UserService; import org.jeecg.modules.miniapp.user.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -91,7 +96,9 @@ public class UserServiceImpl implements UserService {
} }
//update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户 //update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
//1. 校验用户是否有效 //1. 校验用户是否有效
AppUser appUser = getUserByName(username);
LambdaQueryWrapper<AppUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(AppUser::getNickName,username);
AppUser appUser = appUserService.getOne(queryWrapper);
result = (Result<JSONObject>) checkUserIsEffective(appUser); result = (Result<JSONObject>) checkUserIsEffective(appUser);
if(!result.isSuccess()) { if(!result.isSuccess()) {
return result; return result;
@ -112,7 +119,7 @@ public class UserServiceImpl implements UserService {
obj.put("userInfo", appUser); obj.put("userInfo", appUser);
//4. 生成token //4. 生成token
String token = JwtUtil.sign(username, syspassword);
String token = JwtUtil.signMiniApp(username, syspassword);
// 设置超时时间 // 设置超时时间
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token); redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME*2 / 1000); redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME*2 / 1000);
@ -155,7 +162,7 @@ public class UserServiceImpl implements UserService {
return Result.error("退出登录失败!"); return Result.error("退出登录失败!");
} }
String username = JwtUtil.getUsername(token); String username = JwtUtil.getUsername(token);
AppUser appUser = getUserByName(username);
MLoginUser appUser = getMUserByName(username);
if(appUser!=null) { if(appUser!=null) {
//update-begin--Author:wangshuai Date:20200714 for登出日志没有记录人员 //update-begin--Author:wangshuai Date:20200714 for登出日志没有记录人员
baseCommonService.addLog("用户名: "+appUser.getNickName()+",退出成功!", CommonConstant.LOG_TYPE_1, null); baseCommonService.addLog("用户名: "+appUser.getNickName()+",退出成功!", CommonConstant.LOG_TYPE_1, null);
@ -174,11 +181,39 @@ public class UserServiceImpl implements UserService {
} }
@Override @Override
@Cacheable(cacheNames= CacheConstant.SYS_USERS_CACHE, key="#userName")
public AppUser getUserByName(String userName) {
return appUserMapper.getUserByName(userName);
public MLoginUser getMUserByName(String username) {
//update-begin-author:taoyan date:2022-6-6 for: VUEN-1276 v3流程图测试bug 1通过我发起的流程或者流程实例查看历史流程图预览问题
if (oConvertUtils.isEmpty(username)) {
return null;
}
//update-end-author:taoyan date:2022-6-6 for: VUEN-1276 v3流程图测试bug 1通过我发起的流程或者流程实例查看历史流程图预览问题
MLoginUser user = this.getMEncodeUserInfo(username);
//相同类中方法间调用时脱敏解密 Aop会失效获取用户信息太重要此处采用原生解密方法不采用@SensitiveDecodeAble注解方式
try {
SensitiveInfoUtil.handlerObject(user, false);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return user;
} }
@Override
@Cacheable(cacheNames=CacheConstant.SYS_USERS_CACHE, key="#username")
@SensitiveEncode
public MLoginUser getMEncodeUserInfo(String username){
if(oConvertUtils.isEmpty(username)) {
return null;
}
MLoginUser mLoginUser = new MLoginUser();
AppUser appUser = appUserMapper.getUserByName(username);
BeanUtils.copyProperties(appUser, mLoginUser);
return mLoginUser;
}
@Override @Override
public Result<?> checkUserIsEffective(AppUser appUser) { public Result<?> checkUserIsEffective(AppUser appUser) {
Result<?> result = new Result<Object>(); Result<?> result = new Result<Object>();


+ 16
- 10
jeecg-module-system/jeecg-system-api/jeecg-system-cloud-api/src/main/java/org/jeecg/common/system/api/ISysBaseAPI.java View File

@ -85,7 +85,7 @@ public interface ISysBaseAPI extends CommonAPI {
*/ */
@GetMapping("/sys/api/getRolesByUsername") @GetMapping("/sys/api/getRolesByUsername")
List<String> getRolesByUsername(@RequestParam("username") String username); List<String> getRolesByUsername(@RequestParam("username") String username);
/** /**
* 7通过用户账号查询角色集合 * 7通过用户账号查询角色集合
* @param userId * @param userId
@ -101,7 +101,7 @@ public interface ISysBaseAPI extends CommonAPI {
*/ */
@GetMapping("/sys/api/getDepartIdsByUsername") @GetMapping("/sys/api/getDepartIdsByUsername")
List<String> getDepartIdsByUsername(@RequestParam("username") String username); List<String> getDepartIdsByUsername(@RequestParam("username") String username);
/** /**
* 8通过用户账号查询部门集合 * 8通过用户账号查询部门集合
* @param userId * @param userId
@ -125,7 +125,7 @@ public interface ISysBaseAPI extends CommonAPI {
*/ */
@GetMapping("/sys/api/getDepartParentIdsByDepIds") @GetMapping("/sys/api/getDepartParentIdsByDepIds")
Set<String> getDepartParentIdsByDepIds(@RequestParam("depIds") Set<String> depIds); Set<String> getDepartParentIdsByDepIds(@RequestParam("depIds") Set<String> depIds);
/** /**
* 9通过用户账号查询部门 name * 9通过用户账号查询部门 name
* @param username * @param username
@ -320,7 +320,7 @@ public interface ISysBaseAPI extends CommonAPI {
*/ */
@GetMapping("/sys/api/getUserRoleSet") @GetMapping("/sys/api/getUserRoleSet")
Set<String> getUserRoleSet(@RequestParam("username")String username); Set<String> getUserRoleSet(@RequestParam("username")String username);
/** /**
* 30获取用户的角色集合 * 30获取用户的角色集合
* @param userId * @param userId
@ -372,7 +372,7 @@ public interface ISysBaseAPI extends CommonAPI {
@Override @Override
@GetMapping("/sys/api/queryUserRoles") @GetMapping("/sys/api/queryUserRoles")
Set<String> queryUserRoles(@RequestParam("username")String username); Set<String> queryUserRoles(@RequestParam("username")String username);
/** /**
* 35查询用户角色信息 * 35查询用户角色信息
* @param userId * @param userId
@ -420,7 +420,13 @@ public interface ISysBaseAPI extends CommonAPI {
@SensitiveDecode @SensitiveDecode
@GetMapping("/sys/api/getUserByName") @GetMapping("/sys/api/getUserByName")
LoginUser getUserByName(@RequestParam("username") String username); LoginUser getUserByName(@RequestParam("username") String username);
@Override
@SensitiveDecode
@GetMapping("/miniapp/user/getUserByName")
MLoginUser getMUserByName(@RequestParam("username") String username);
/** /**
* 39根据用户账号查询用户ID CommonAPI中定义 * 39根据用户账号查询用户ID CommonAPI中定义
* @param username * @param username
@ -503,7 +509,7 @@ public interface ISysBaseAPI extends CommonAPI {
// */ // */
// @GetMapping("/sys/api/queryDepartsByOrgIds") // @GetMapping("/sys/api/queryDepartsByOrgIds")
// List<JSONObject> queryDepartsByOrgIds(@RequestParam("ids") String ids); // List<JSONObject> queryDepartsByOrgIds(@RequestParam("ids") String ids);
/** /**
* 40发送邮件消息 * 40发送邮件消息
* @param email * @param email
@ -563,11 +569,11 @@ public interface ISysBaseAPI extends CommonAPI {
* @param originalAppId 原始低代码应用ID * @param originalAppId 原始低代码应用ID
* @param appId 新的低代码应用ID * @param appId 新的低代码应用ID
* @param tenantId 新的租户ID * @param tenantId 新的租户ID
* @return Map<String, String> Map<原字典编码, 新字典编码>
* @return Map<String, String> Map<原字典编码, 新字典编码>
*/ */
@GetMapping("/sys/api/copyLowAppDict") @GetMapping("/sys/api/copyLowAppDict")
Map<String, String> copyLowAppDict(@RequestParam("originalAppId") String originalAppId, @RequestParam("appId") String appId, @RequestParam("tenantId") String tenantId); Map<String, String> copyLowAppDict(@RequestParam("originalAppId") String originalAppId, @RequestParam("appId") String appId, @RequestParam("tenantId") String tenantId);
/** /**
* 44 根据字典code查询字典项 * 44 根据字典code查询字典项
* *
@ -744,7 +750,7 @@ public interface ISysBaseAPI extends CommonAPI {
*/ */
@GetMapping("/sys/api/queryUserAccountsByDeptIds") @GetMapping("/sys/api/queryUserAccountsByDeptIds")
List<String> queryUserAccountsByDeptIds(List<String> deptIds); List<String> queryUserAccountsByDeptIds(List<String> deptIds);
/** /**
* 根据角色编码 查询用户ID * 根据角色编码 查询用户ID
* @param roleCodes * @param roleCodes


+ 7
- 1
jeecg-module-system/jeecg-system-api/jeecg-system-cloud-api/src/main/java/org/jeecg/common/system/api/fallback/SysBaseAPIFallback.java View File

@ -259,6 +259,12 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
return null; return null;
} }
@Override
public MLoginUser getMUserByName(String username) {
log.error("jeecg-system服务节点不通,导致获取登录用户信息失败: " + cause.getMessage(), cause);
return null;
}
@Override @Override
public String getUserIdByName(String username) { public String getUserIdByName(String username) {
return null; return null;
@ -391,7 +397,7 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
@Override @Override
public void sendAppChatSocket(String userId) { public void sendAppChatSocket(String userId) {
} }
@Override @Override


+ 13
- 0
jeecg-module-system/jeecg-system-biz/pom.xml View File

@ -20,6 +20,13 @@
<artifactId>jeecg-module-demo</artifactId> <artifactId>jeecg-module-demo</artifactId>
<version>3.7.2</version> <version>3.7.2</version>
</dependency> </dependency>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-module-miniapp</artifactId>
<version>3.7.2</version>
</dependency>
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId> <artifactId>hibernate-core</artifactId>
@ -48,6 +55,12 @@
<groupId>org.jeecgframework.jimureport</groupId> <groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimubi-spring-boot-starter</artifactId> <artifactId>jimubi-spring-boot-starter</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-module-miniapp</artifactId>
<version>3.7.2</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

+ 19
- 19
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/LoginController.java View File

@ -81,24 +81,24 @@ public class LoginController {
} }
// step.1 验证码check // step.1 验证码check
String captcha = sysLoginModel.getCaptcha();
if(captcha==null){
result.error500("验证码无效");
return result;
}
String lowerCaseCaptcha = captcha.toLowerCase();
// 加入密钥作为混淆避免简单的拼接被外部利用用户自定义该密钥即可
String origin = lowerCaseCaptcha+sysLoginModel.getCheckKey()+jeecgBaseConfig.getSignatureSecret();
String realKey = Md5Util.md5Encode(origin, "utf-8");
Object checkCode = redisUtil.get(realKey);
//当进入登录页时有一定几率出现验证码错误 #1714
if(checkCode==null || !checkCode.toString().equals(lowerCaseCaptcha)) {
log.warn("验证码错误,key= {} , Ui checkCode= {}, Redis checkCode = {}", sysLoginModel.getCheckKey(), lowerCaseCaptcha, checkCode);
result.error500("验证码错误");
// 改成特殊的code 便于前端判断
result.setCode(HttpStatus.PRECONDITION_FAILED.value());
return result;
}
// String captcha = sysLoginModel.getCaptcha();
// if(captcha==null){
// result.error500("验证码无效");
// return result;
// }
// String lowerCaseCaptcha = captcha.toLowerCase();
// // 加入密钥作为混淆避免简单的拼接被外部利用用户自定义该密钥即可
// String origin = lowerCaseCaptcha+sysLoginModel.getCheckKey()+jeecgBaseConfig.getSignatureSecret();
// String realKey = Md5Util.md5Encode(origin, "utf-8");
// Object checkCode = redisUtil.get(realKey);
// //当进入登录页时有一定几率出现验证码错误 #1714
// if(checkCode==null || !checkCode.toString().equals(lowerCaseCaptcha)) {
// log.warn("验证码错误,key= {} , Ui checkCode= {}, Redis checkCode = {}", sysLoginModel.getCheckKey(), lowerCaseCaptcha, checkCode);
// result.error500("验证码错误");
// // 改成特殊的code 便于前端判断
// result.setCode(HttpStatus.PRECONDITION_FAILED.value());
// return result;
// }
// step.2 校验用户是否存在且有效 // step.2 校验用户是否存在且有效
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
@ -122,7 +122,7 @@ public class LoginController {
userInfo(sysUser, result, request); userInfo(sysUser, result, request);
// step.5 登录成功删除验证码 // step.5 登录成功删除验证码
redisUtil.del(realKey);
// redisUtil.del(realKey);
redisUtil.del(CommonConstant.LOGIN_FAIL + username); redisUtil.del(CommonConstant.LOGIN_FAIL + username);
// step.6 记录用户登录日志 // step.6 记录用户登录日志


+ 14
- 13
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/ISysUserService.java View File

@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.api.vo.Result; import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.MLoginUser;
import org.jeecg.common.system.vo.SysUserCacheInfo; import org.jeecg.common.system.vo.SysUserCacheInfo;
import org.jeecg.modules.system.entity.SysRoleIndex; import org.jeecg.modules.system.entity.SysRoleIndex;
import org.jeecg.modules.system.entity.SysUser; import org.jeecg.modules.system.entity.SysUser;
@ -35,7 +36,7 @@ public interface ISysUserService extends IService<SysUser> {
/** /**
* 查询用户数据列表 * 查询用户数据列表
*
*
* @param req * @param req
* @param queryWrapper * @param queryWrapper
* @param pageSize * @param pageSize
@ -43,7 +44,7 @@ public interface ISysUserService extends IService<SysUser> {
* @return * @return
*/ */
Result<IPage<SysUser>> queryPageList(HttpServletRequest req, QueryWrapper<SysUser> queryWrapper, Integer pageSize, Integer pageNo); Result<IPage<SysUser>> queryPageList(HttpServletRequest req, QueryWrapper<SysUser> queryWrapper, Integer pageSize, Integer pageNo);
/** /**
* 重置密码 * 重置密码
* *
@ -83,15 +84,15 @@ public interface ISysUserService extends IService<SysUser> {
* @return SysUser * @return SysUser
*/ */
public SysUser getUserByName(String username); public SysUser getUserByName(String username);
/** /**
* 添加用户和用户角色关系 * 添加用户和用户角色关系
* @param user * @param user
* @param roles * @param roles
*/ */
public void addUserWithRole(SysUser user,String roles); public void addUserWithRole(SysUser user,String roles);
/** /**
* 修改用户和用户角色关系 * 修改用户和用户角色关系
* @param user * @param user
@ -114,7 +115,7 @@ public interface ISysUserService extends IService<SysUser> {
* @return * @return
*/ */
public SysRoleIndex getDynamicIndexByUserRole(String username,String version); public SysRoleIndex getDynamicIndexByUserRole(String username,String version);
/** /**
* 查询用户信息包括 部门信息 * 查询用户信息包括 部门信息
* @param username * @param username
@ -186,7 +187,7 @@ public interface ISysUserService extends IService<SysUser> {
* @return 角色集合 * @return 角色集合
*/ */
Set<String> getUserRolesSet(String username); Set<String> getUserRolesSet(String username);
/** /**
* 通过用户名获取用户角色集合 * 通过用户名获取用户角色集合
* *
@ -202,14 +203,14 @@ public interface ISysUserService extends IService<SysUser> {
* @return 权限集合 * @return 权限集合
*/ */
Set<String> getUserPermissionsSet(String userId); Set<String> getUserPermissionsSet(String userId);
/** /**
* 根据用户名设置部门ID * 根据用户名设置部门ID
* @param username * @param username
* @param orgCode * @param orgCode
*/ */
void updateUserDepart(String username,String orgCode,Integer loginTenantId); void updateUserDepart(String username,String orgCode,Integer loginTenantId);
/** /**
* 根据手机号获取用户名和密码 * 根据手机号获取用户名和密码
* @param phone 手机号 * @param phone 手机号
@ -239,7 +240,7 @@ public interface ISysUserService extends IService<SysUser> {
* @param departs * @param departs
*/ */
void editUserWithDepart(SysUser user, String departs); void editUserWithDepart(SysUser user, String departs);
/** /**
* 校验用户是否有效 * 校验用户是否有效
* @param sysUser * @param sysUser
@ -391,7 +392,7 @@ public interface ISysUserService extends IService<SysUser> {
*/ */
void changeDepartChargePerson(JSONObject json); void changeDepartChargePerson(JSONObject json);
//--- author:taoyan date:20221231 for: QQYUN-3515应用应用下的组织机构管理功能细节实现 --- //--- author:taoyan date:20221231 for: QQYUN-3515应用应用下的组织机构管理功能细节实现 ---
/** /**
* 编辑租户用户 * 编辑租户用户
* @param sysUser * @param sysUser
@ -429,7 +430,7 @@ public interface ISysUserService extends IService<SysUser> {
/** /**
* 修改手机号 * 修改手机号
*
*
* @param json * @param json
* @param username * @param username
*/ */
@ -437,7 +438,7 @@ public interface ISysUserService extends IService<SysUser> {
/** /**
* 发送短信验证码 * 发送短信验证码
*
*
* @param jsonObject * @param jsonObject
* @param username 用户名 * @param username 用户名
* @param ipAddress ip地址 * @param ipAddress ip地址


+ 41
- 18
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysBaseApiImpl.java View File

@ -46,6 +46,7 @@ import org.jeecg.modules.message.handle.impl.QywxSendMsgHandle;
import org.jeecg.modules.message.handle.impl.SystemSendMsgHandle; import org.jeecg.modules.message.handle.impl.SystemSendMsgHandle;
import org.jeecg.modules.message.service.ISysMessageTemplateService; import org.jeecg.modules.message.service.ISysMessageTemplateService;
import org.jeecg.modules.message.websocket.WebSocket; import org.jeecg.modules.message.websocket.WebSocket;
import org.jeecg.modules.miniapp.user.service.impl.UserServiceImpl;
import org.jeecg.modules.system.entity.*; import org.jeecg.modules.system.entity.*;
import org.jeecg.modules.system.mapper.*; import org.jeecg.modules.system.mapper.*;
import org.jeecg.modules.system.service.*; import org.jeecg.modules.system.service.*;
@ -74,7 +75,7 @@ import java.util.stream.Collectors;
/** /**
* @Description: 底层共通业务API提供其他独立模块调用 * @Description: 底层共通业务API提供其他独立模块调用
* @Author: scott * @Author: scott
* @Date:2019-4-20
* @Date:2019-4-20
* @Version:V1.0 * @Version:V1.0
*/ */
@Slf4j @Slf4j
@ -137,6 +138,9 @@ public class SysBaseApiImpl implements ISysBaseAPI {
@Autowired @Autowired
private IDictTableWhiteListHandler dictTableWhiteListHandler; private IDictTableWhiteListHandler dictTableWhiteListHandler;
@Autowired
private UserServiceImpl userService;
@Override @Override
//@SensitiveDecode //@SensitiveDecode
public LoginUser getUserByName(String username) { public LoginUser getUserByName(String username) {
@ -157,6 +161,25 @@ public class SysBaseApiImpl implements ISysBaseAPI {
return user; return user;
} }
@Override
public MLoginUser getMUserByName(String username) {
//update-begin-author:taoyan date:2022-6-6 for: VUEN-1276 v3流程图测试bug 1通过我发起的流程或者流程实例查看历史流程图预览问题
if (oConvertUtils.isEmpty(username)) {
return null;
}
//update-end-author:taoyan date:2022-6-6 for: VUEN-1276 v3流程图测试bug 1通过我发起的流程或者流程实例查看历史流程图预览问题
MLoginUser user = userService.getMUserByName(username);
//相同类中方法间调用时脱敏解密 Aop会失效获取用户信息太重要此处采用原生解密方法不采用@SensitiveDecodeAble注解方式
try {
SensitiveInfoUtil.handlerObject(user, false);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return user;
}
@Override @Override
@Cacheable(cacheNames=CommonConstant.SYS_USER_ID_MAPPING_CACHE, key="#username") @Cacheable(cacheNames=CommonConstant.SYS_USER_ID_MAPPING_CACHE, key="#username")
@ -167,7 +190,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
String userId = userMapper.getUserIdByName(username); String userId = userMapper.getUserIdByName(username);
return userId; return userId;
} }
@Override @Override
public String translateDictFromTable(String table, String text, String code, String key) { public String translateDictFromTable(String table, String text, String code, String key) {
@ -193,17 +216,17 @@ public class SysBaseApiImpl implements ISysBaseAPI {
LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<SysPermission>(); LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<SysPermission>();
query.eq(SysPermission::getMenuType,2); query.eq(SysPermission::getMenuType,2);
query.eq(SysPermission::getDelFlag,0); query.eq(SysPermission::getDelFlag,0);
//update-begin-author:taoyan date:2023-2-21 for: 解决参数顺序问题 //update-begin-author:taoyan date:2023-2-21 for: 解决参数顺序问题
List<String> allPossiblePaths = this.getOnlinePossiblePaths(requestPath); List<String> allPossiblePaths = this.getOnlinePossiblePaths(requestPath);
log.info("获取的菜单地址= {}", allPossiblePaths.toString()); log.info("获取的菜单地址= {}", allPossiblePaths.toString());
if(allPossiblePaths.size()==1){ if(allPossiblePaths.size()==1){
query.eq(SysPermission::getUrl, requestPath); query.eq(SysPermission::getUrl, requestPath);
}else{ }else{
query.in(SysPermission::getUrl, allPossiblePaths);
query.in(SysPermission::getUrl, allPossiblePaths);
} }
//update-end-author:taoyan date:2023-2-21 for: 解决参数顺序问题 //update-end-author:taoyan date:2023-2-21 for: 解决参数顺序问题
currentSyspermission = sysPermissionMapper.selectList(query); currentSyspermission = sysPermissionMapper.selectList(query);
//2.未找到 再通过自定义匹配URL 获取菜单 //2.未找到 再通过自定义匹配URL 获取菜单
if(currentSyspermission==null || currentSyspermission.size()==0) { if(currentSyspermission==null || currentSyspermission.size()==0) {
@ -326,7 +349,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
public List<String> getRolesByUsername(String username) { public List<String> getRolesByUsername(String username) {
return sysUserRoleMapper.getRoleByUserName(username); return sysUserRoleMapper.getRoleByUserName(username);
} }
@Override @Override
public List<String> getRolesByUserId(String userId) { public List<String> getRolesByUserId(String userId) {
return sysUserRoleMapper.getRoleCodeByUserId(userId); return sysUserRoleMapper.getRoleCodeByUserId(userId);
@ -341,7 +364,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
} }
return result; return result;
} }
@Override @Override
public List<String> getDepartIdsByUserId(String userId) { public List<String> getDepartIdsByUserId(String userId) {
return sysDepartService.queryDepartsByUserId(userId); return sysDepartService.queryDepartsByUserId(userId);
@ -558,7 +581,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
announcement.setMsgType(CommonConstant.MSG_TYPE_UESR); announcement.setMsgType(CommonConstant.MSG_TYPE_UESR);
announcement.setSendStatus(CommonConstant.HAS_SEND); announcement.setSendStatus(CommonConstant.HAS_SEND);
announcement.setSendTime(new Date()); announcement.setSendTime(new Date());
if(tmplateParam!=null && oConvertUtils.isNotEmpty(tmplateParam.get(CommonSendStatus.MSG_ABSTRACT_JSON))){ if(tmplateParam!=null && oConvertUtils.isNotEmpty(tmplateParam.get(CommonSendStatus.MSG_ABSTRACT_JSON))){
announcement.setMsgAbstract(tmplateParam.get(CommonSendStatus.MSG_ABSTRACT_JSON)); announcement.setMsgAbstract(tmplateParam.get(CommonSendStatus.MSG_ABSTRACT_JSON));
} }
@ -566,7 +589,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
if(tmplateParam!=null && oConvertUtils.isNotEmpty(tmplateParam.get(CommonConstant.MSG_HREF_URL))){ if(tmplateParam!=null && oConvertUtils.isNotEmpty(tmplateParam.get(CommonConstant.MSG_HREF_URL))){
mobileOpenUrl = tmplateParam.get(CommonConstant.MSG_HREF_URL); mobileOpenUrl = tmplateParam.get(CommonConstant.MSG_HREF_URL);
} }
announcement.setMsgCategory(CommonConstant.MSG_CATEGORY_2); announcement.setMsgCategory(CommonConstant.MSG_CATEGORY_2);
announcement.setDelFlag(String.valueOf(CommonConstant.DEL_FLAG_0)); announcement.setDelFlag(String.valueOf(CommonConstant.DEL_FLAG_0));
announcement.setBusId(busId); announcement.setBusId(busId);
@ -848,7 +871,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
} else { } else {
queryWrapper.like("depart_ids", deptId); queryWrapper.like("depart_ids", deptId);
} }
List<SysUser> userList = userMapper.selectList(queryWrapper); List<SysUser> userList = userMapper.selectList(queryWrapper);
List<String> list = new ArrayList<>(); List<String> list = new ArrayList<>();
for(SysUser user : userList){ for(SysUser user : userList){
@ -915,7 +938,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
QueryWrapper<SysUser> queryWrapper = QueryGenerator.initQueryWrapper(sysUser, parameterMap); QueryWrapper<SysUser> queryWrapper = QueryGenerator.initQueryWrapper(sysUser, parameterMap);
List<SysUser> list= sysUserService.list(queryWrapper); List<SysUser> list= sysUserService.list(queryWrapper);
if(ObjectUtils.isNotEmpty(list)){ if(ObjectUtils.isNotEmpty(list)){
//update-begin-author:taoyan date:2023-5-19 for: QQYUN-5326简流获取组织人员 / 筛选条件 没有部门筛选 //update-begin-author:taoyan date:2023-5-19 for: QQYUN-5326简流获取组织人员 / 筛选条件 没有部门筛选
String departKey = "depart"; String departKey = "depart";
QueryCondition departCondition = null; QueryCondition departCondition = null;
@ -931,7 +954,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
log.error("查询用户信息,查询条件json转化失败", e); log.error("查询用户信息,查询条件json转化失败", e);
} }
for (SysUser user : list) { for (SysUser user : list) {
JSONObject userJson = JSONObject.parseObject(JSONObject.toJSONString(user)); JSONObject userJson = JSONObject.parseObject(JSONObject.toJSONString(user));
List<SysDepart> departList = sysDepartService.queryDepartsByUsername(user.getUsername()); List<SysDepart> departList = sysDepartService.queryDepartsByUsername(user.getUsername());
@ -947,7 +970,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
result.add(userJson); result.add(userJson);
} }
//update-end-author:taoyan date:2023-5-19 for: QQYUN-5326简流获取组织人员 / 筛选条件 没有部门筛选 //update-end-author:taoyan date:2023-5-19 for: QQYUN-5326简流获取组织人员 / 筛选条件 没有部门筛选
} }
} }
return result; return result;
@ -1117,8 +1140,8 @@ public class SysBaseApiImpl implements ISysBaseAPI {
log.info("-------通过数据库读取用户拥有的角色Rules------username: " + username + ",Roles size: " + (roles == null ? 0 : roles.size())); log.info("-------通过数据库读取用户拥有的角色Rules------username: " + username + ",Roles size: " + (roles == null ? 0 : roles.size()));
return new HashSet<>(roles); return new HashSet<>(roles);
} }
/** /**
* 查询用户拥有的角色集合 * 查询用户拥有的角色集合
* @param useId * @param useId
@ -1375,7 +1398,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
EmailSendMsgHandle emailHandle=new EmailSendMsgHandle(); EmailSendMsgHandle emailHandle=new EmailSendMsgHandle();
emailHandle.sendMsg(email, title, content); emailHandle.sendMsg(email, title, content);
} }
/** /**
* 发送html模版邮件消息 * 发送html模版邮件消息
* @param email * @param email
@ -1708,7 +1731,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
queryWrapper.lambda().select(SysUserDepart::getUserId).in(true,SysUserDepart::getDepId,deptIds); queryWrapper.lambda().select(SysUserDepart::getUserId).in(true,SysUserDepart::getDepId,deptIds);
return sysUserDepartService.listObjs(queryWrapper,e->e.toString()); return sysUserDepartService.listObjs(queryWrapper,e->e.toString());
} }
@Override @Override
public List<String> queryUserAccountsByDeptIds(List<String> deptIds) { public List<String> queryUserAccountsByDeptIds(List<String> deptIds) {
return departMapper.queryUserAccountByDepartIds(deptIds); return departMapper.queryUserAccountByDepartIds(deptIds);
@ -1825,4 +1848,4 @@ public class SysBaseApiImpl implements ISysBaseAPI {
} }
} }
}
}

+ 27
- 22
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysUserServiceImpl.java View File

@ -30,11 +30,14 @@ import org.jeecg.common.constant.enums.SysAnnmentTypeEnum;
import org.jeecg.common.desensitization.annotation.SensitiveEncode; import org.jeecg.common.desensitization.annotation.SensitiveEncode;
import org.jeecg.common.exception.JeecgBootException; import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.MLoginUser;
import org.jeecg.common.system.vo.SysUserCacheInfo; import org.jeecg.common.system.vo.SysUserCacheInfo;
import org.jeecg.common.util.*; import org.jeecg.common.util.*;
import org.jeecg.config.mybatis.MybatisPlusSaasConfig; import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
import org.jeecg.modules.base.service.BaseCommonService; import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.modules.message.handle.impl.SystemSendMsgHandle; import org.jeecg.modules.message.handle.impl.SystemSendMsgHandle;
import org.jeecg.modules.sysMiniapp.appuser.entity.AppUser;
import org.jeecg.modules.sysMiniapp.appuser.mapper.AppUserMapper;
import org.jeecg.modules.system.entity.*; import org.jeecg.modules.system.entity.*;
import org.jeecg.modules.system.mapper.*; import org.jeecg.modules.system.mapper.*;
import org.jeecg.modules.system.model.SysUserSysDepartModel; import org.jeecg.modules.system.model.SysUserSysDepartModel;
@ -81,7 +84,7 @@ import java.util.stream.Collectors;
@Service @Service
@Slf4j @Slf4j
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService { public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {
@Autowired @Autowired
private SysUserMapper userMapper; private SysUserMapper userMapper;
@Autowired @Autowired
@ -124,7 +127,9 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
private ISysThirdAccountService sysThirdAccountService; private ISysThirdAccountService sysThirdAccountService;
@Autowired @Autowired
private RedisUtil redisUtil; private RedisUtil redisUtil;
@Autowired
private AppUserMapper appUserMapper;
@Override @Override
public Result<IPage<SysUser>> queryPageList(HttpServletRequest req, QueryWrapper<SysUser> queryWrapper, Integer pageSize, Integer pageNo) { public Result<IPage<SysUser>> queryPageList(HttpServletRequest req, QueryWrapper<SysUser> queryWrapper, Integer pageSize, Integer pageNo) {
Result<IPage<SysUser>> result = new Result<IPage<SysUser>>(); Result<IPage<SysUser>> result = new Result<IPage<SysUser>>();
@ -172,7 +177,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
// } // }
// } // }
//update-end---author:wangshuai---date:2024-03-08---for:QQYUN-8110在线通讯录支持设置权限(只能看分配的技术支持)--- //update-end---author:wangshuai---date:2024-03-08---for:QQYUN-8110在线通讯录支持设置权限(只能看分配的技术支持)---
//TODO 外部模拟登陆临时账号列表不显示 //TODO 外部模拟登陆临时账号列表不显示
queryWrapper.ne("username", "_reserve_user_external"); queryWrapper.ne("username", "_reserve_user_external");
Page<SysUser> page = new Page<SysUser>(pageNo, pageSize); Page<SysUser> page = new Page<SysUser>(pageNo, pageSize);
@ -195,7 +200,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
} }
Integer posTenantId = null; Integer posTenantId = null;
if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) { if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
posTenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);;
posTenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);;
} }
//查询用户职位关系表(获取租户下面的) //查询用户职位关系表(获取租户下面的)
//update-begin---author:wangshuai---date:2023-11-15---for:QQYUN-7028用户职务保存后未回显--- //update-begin---author:wangshuai---date:2023-11-15---for:QQYUN-7028用户职务保存后未回显---
@ -203,7 +208,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
//update-end---author:wangshuai---date:2023-11-15---for:QQYUN-7028用户职务保存后未回显--- //update-end---author:wangshuai---date:2023-11-15---for:QQYUN-7028用户职务保存后未回显---
//update-end---author:wangshuai ---date:20230228 for[QQYUN-4354]加入更多字段当前加入时间应该取当前租户的/职位也是当前租户下的------------ //update-end---author:wangshuai ---date:20230228 for[QQYUN-4354]加入更多字段当前加入时间应该取当前租户的/职位也是当前租户下的------------
item.setPost(CommonUtils.getSplitText(positionList,SymbolConstant.COMMA)); item.setPost(CommonUtils.getSplitText(positionList,SymbolConstant.COMMA));
//update-begin---author:wangshuai---date:2023-10-08---for:QQYUN-6668钉钉部门和用户同步我怎么知道哪些用户是双向绑定成功的--- //update-begin---author:wangshuai---date:2023-10-08---for:QQYUN-6668钉钉部门和用户同步我怎么知道哪些用户是双向绑定成功的---
//是否根据租户隔离(敲敲云用户列表专用用于展示是否同步钉钉) //是否根据租户隔离(敲敲云用户列表专用用于展示是否同步钉钉)
if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) { if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
@ -293,8 +298,8 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
} }
return sysUser; return sysUser;
} }
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void addUserWithRole(SysUser user, String roles) { public void addUserWithRole(SysUser user, String roles) {
@ -382,7 +387,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
log.info("-------通过数据库读取用户拥有的角色Rules------username: " + username + ",Roles size: " + (roles == null ? 0 : roles.size())); log.info("-------通过数据库读取用户拥有的角色Rules------username: " + username + ",Roles size: " + (roles == null ? 0 : roles.size()));
return new HashSet<>(roles); return new HashSet<>(roles);
} }
/** /**
* 通过用户名获取用户角色集合 * 通过用户名获取用户角色集合
* @param userId 用户ID * @param userId 用户ID
@ -450,7 +455,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
info.setSysUserName(sysUser.getRealname()); info.setSysUserName(sysUser.getRealname());
info.setSysOrgCode(sysUser.getOrgCode()); info.setSysOrgCode(sysUser.getOrgCode());
} }
//多部门支持in查询 //多部门支持in查询
List<SysDepart> list = sysDepartMapper.queryUserDeparts(sysUser.getId()); List<SysDepart> list = sysDepartMapper.queryUserDeparts(sysUser.getId());
List<String> sysMultiOrgCode = new ArrayList<String>(); List<String> sysMultiOrgCode = new ArrayList<String>();
@ -466,7 +471,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
} }
} }
info.setSysMultiOrgCode(sysMultiOrgCode); info.setSysMultiOrgCode(sysMultiOrgCode);
return info; return info;
} }
@ -703,7 +708,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
//6. 删除租户用户中间表的数据 //6. 删除租户用户中间表的数据
line += userTenantMapper.delete(new LambdaQueryWrapper<SysUserTenant>().in(SysUserTenant::getUserId,userIds)); line += userTenantMapper.delete(new LambdaQueryWrapper<SysUserTenant>().in(SysUserTenant::getUserId,userIds));
return line != 0; return line != 0;
} }
@ -750,7 +755,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
sysUserRoleMapper.insert(userRole); sysUserRoleMapper.insert(userRole);
} }
} }
//step.3 保存所属部门 //step.3 保存所属部门
if(oConvertUtils.isNotEmpty(selectedDeparts)) { if(oConvertUtils.isNotEmpty(selectedDeparts)) {
String[] arr = selectedDeparts.split(","); String[] arr = selectedDeparts.split(",");
@ -977,7 +982,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
relation.setUserId(userId); relation.setUserId(userId);
relation.setTenantId(Integer.valueOf(tenantId)); relation.setTenantId(Integer.valueOf(tenantId));
relation.setStatus(CommonConstant.STATUS_1); relation.setStatus(CommonConstant.STATUS_1);
LambdaQueryWrapper sysUserTenantQueryWrapper = new LambdaQueryWrapper<SysUserTenant>() LambdaQueryWrapper sysUserTenantQueryWrapper = new LambdaQueryWrapper<SysUserTenant>()
.eq(SysUserTenant::getUserId, userId) .eq(SysUserTenant::getUserId, userId)
.eq(SysUserTenant::getTenantId,Integer.valueOf(tenantId)); .eq(SysUserTenant::getTenantId,Integer.valueOf(tenantId));
@ -1031,7 +1036,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
//找到新的租户id与原来的租户id不同之处进行删除 //找到新的租户id与原来的租户id不同之处进行删除
String[] relTenantIdArray = relTenantIds.split(SymbolConstant.COMMA); String[] relTenantIdArray = relTenantIds.split(SymbolConstant.COMMA);
List<String> relTenantIdList = Arrays.asList(relTenantIdArray); List<String> relTenantIdList = Arrays.asList(relTenantIdArray);
List<Integer> deleteTenantIdList = oldTenantIds.stream().filter(item -> !relTenantIdList.contains(item.toString())).collect(Collectors.toList()); List<Integer> deleteTenantIdList = oldTenantIds.stream().filter(item -> !relTenantIdList.contains(item.toString())).collect(Collectors.toList());
for (Integer tenantId : deleteTenantIdList) { for (Integer tenantId : deleteTenantIdList) {
this.deleteTenantByUserId(userId, tenantId); this.deleteTenantByUserId(userId, tenantId);
@ -1102,9 +1107,9 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
.in(SysUserDepart::getUserId, idList) .in(SysUserDepart::getUserId, idList)
.in(SysUserDepart::getDepId, departIdList); .in(SysUserDepart::getDepId, departIdList);
sysUserDepartMapper.delete(query); sysUserDepartMapper.delete(query);
String[] arr = selecteddeparts.split(","); String[] arr = selecteddeparts.split(",");
//再新增 //再新增
for (String deaprtId : arr) { for (String deaprtId : arr) {
for(String userId: idList){ for(String userId: idList){
@ -1236,7 +1241,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
this.removeDepartmentManager(departChargeUserIdList,departChargeUsers,departId); this.removeDepartmentManager(departChargeUserIdList,departChargeUsers,departId);
} }
//update-end---author:wangshuai ---date:20230303 for部门负责人不能被删除------------ //update-end---author:wangshuai ---date:20230303 for部门负责人不能被删除------------
} }
} }
} }
@ -1263,7 +1268,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
} }
return result; return result;
} }
/** /**
* 变更父级部门 修改编码 * 变更父级部门 修改编码
* @param parentId * @param parentId
@ -1343,7 +1348,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
getParentDepart(temp, orgName, orgId); getParentDepart(temp, orgName, orgId);
} }
} }
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true) @CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
@ -1408,7 +1413,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
} }
long endTime1 = System.currentTimeMillis(); long endTime1 = System.currentTimeMillis();
System.out.println("修改部门角色用时:" + (endTime1 - startTime) + "ms"); System.out.println("修改部门角色用时:" + (endTime1 - startTime) + "ms");
if (departList.size() > 0) { if (departList.size() > 0) {
//删除用户下的部门 //删除用户下的部门
sysUserDepartMapper.deleteUserDepart(user.getId(), tenantId); sysUserDepartMapper.deleteUserDepart(user.getId(), tenantId);
@ -1862,7 +1867,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
* @param userId * @param userId
* @param tenantId * @param tenantId
* @param invitedUsername 被邀请人的账号 * @param invitedUsername 被邀请人的账号
* @param tenantName 租户名称
* @param tenantName 租户名称
*/ */
private void addUserTenant(String userId, Integer tenantId, String invitedUsername, String tenantName) { private void addUserTenant(String userId, Integer tenantId, String invitedUsername, String tenantName) {
SysUserTenant userTenant = new SysUserTenant(); SysUserTenant userTenant = new SysUserTenant();
@ -1888,7 +1893,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
//update-end---author:wangshuai ---date:20230710 forQQYUN-5731导入用户时没有提醒------------ //update-end---author:wangshuai ---date:20230710 forQQYUN-5731导入用户时没有提醒------------
} }
//======================================= end 用户与部门 用户列表导入 ========================================= //======================================= end 用户与部门 用户列表导入 =========================================
@Override @Override
public void checkUserAdminRejectDel(String userIds) { public void checkUserAdminRejectDel(String userIds) {
LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<>();


+ 1
- 1
jeecg-module-system/jeecg-system-start/src/main/resources/logback-spring.xml View File

@ -74,4 +74,4 @@
<appender-ref ref="FILE_HTML" /> <appender-ref ref="FILE_HTML" />
</root> </root>
</configuration>
</configuration>

Loading…
Cancel
Save