refactor(user): update user information retrieval to use UserDTO and improve method documentation

This commit is contained in:
PIG AI committed 2025-07-04 11:58:50 +08:00
1 parent 3a53fb5677
commit d3770993ce
54 files changed
+810 -813

No files matched your search

@@ -27,13 +27,11 @@ import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum;
import com.pig4cloud.pigx.common.core.exception.ErrorCodes;
import com.pig4cloud.pigx.common.core.util.MsgUtils;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
/**
* @author lengleng
* @date 2018/11/14
@@ -45,8 +43,6 @@ import java.util.concurrent.TimeUnit;
@AllArgsConstructor
public class AppMobileServiceImpl implements AppMobileService {
private final StringRedisTemplate redisTemplate;
/**
* 发送手机验证码 TODO: 调用短信网关发送验证码,测试返回前端
* @param mobile mobile
@@ -54,8 +50,7 @@ public class AppMobileServiceImpl implements AppMobileService {
*/
@Override
public R<Boolean> sendSmsCode(String mobile) {
String codeObj = redisTemplate.opsForValue()
.get(CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.APPSMS.getType() + StringPool.AT + mobile);
String codeObj = RedisUtils.get(CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.APPSMS.getType() + StringPool.AT + mobile);
if (StrUtil.isNotBlank(codeObj)) {
log.info("手机号验证码未过期:{},{}", mobile, codeObj);
@@ -64,9 +59,7 @@ public class AppMobileServiceImpl implements AppMobileService {
String code = RandomUtil.randomNumbers(Integer.parseInt(SecurityConstants.CODE_SIZE));
log.debug("手机号生成验证码成功:{},{}", mobile, code);
redisTemplate.opsForValue()
.set(CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.APPSMS.getType() + StringPool.AT + mobile, code,
SecurityConstants.CODE_TIME, TimeUnit.SECONDS);
RedisUtils.set(CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.APPSMS.getType() + StringPool.AT + mobile, code, SecurityConstants.CODE_TIME);
return R.ok(Boolean.TRUE);
}
@@ -42,6 +42,7 @@ import com.pig4cloud.pigx.common.core.constant.enums.UserTypeEnum;
import com.pig4cloud.pigx.common.core.exception.ErrorCodes;
import com.pig4cloud.pigx.common.core.util.MsgUtils;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import com.pig4cloud.pigx.common.excel.vo.ErrorMessage;
import com.pig4cloud.pigx.common.security.service.PigxUser;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
@@ -51,7 +52,6 @@ import org.springframework.beans.BeanUtils;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
@@ -60,10 +60,9 @@ import org.springframework.validation.BindingResult;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* app用户表
* app用户表服务实现类
*
* @author aeizzz
* @date 2022-12-07 09:52:03
@@ -73,156 +72,227 @@ import java.util.stream.Collectors;
@Slf4j
public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> implements AppUserService {
/**
* 密码编码器,用于密码加密
*/
private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();
/**
* 用户角色关联服务
*/
private final AppUserRoleService appUserRoleService;
private final StringRedisTemplate redisTemplate;
/**
* 角色服务
*/
private final AppRoleService appRoleService;
/**
* 缓存管理器
*/
private final CacheManager cacheManager;
/**
* 更新用户
* @param userDTO
* @return
* 更新用户信息
* @param userDTO 用户数据传输对象
* @return 更新结果
*/
@Override
@CacheEvict(value = CacheConstants.USER_DETAILS_MINI, key = "#userDTO.username")
public Boolean updateUser(AppUserDTO userDTO) {
// 创建用户实体并复制属性
AppUser appUser = new AppUser();
BeanUtils.copyProperties(userDTO, appUser);
// 如果密码不为空,进行加密处理
if (StrUtil.isNotBlank(userDTO.getPassword())) {
appUser.setPassword(ENCODER.encode(userDTO.getPassword()));
}
// 更新用户基本信息
this.updateById(appUser);
// 删除用户与角色的关联关系
appUserRoleService.remove(Wrappers.<AppUserRole>lambdaQuery().eq(AppUserRole::getUserId, appUser.getUserId()));
// 重新建立用户与角色的关联关系
userDTO.getRole().forEach(roleId -> {
AppUserRole appUserRole = new AppUserRole();
appUserRole.setRoleId(roleId);
appUserRole.setUserId(userDTO.getUserId());
appUserRole.insert();
});
// 清除以手机号为key的用户缓存
AppUser appUserInfo = baseMapper.selectById(userDTO.getUserId());
cacheManager.getCache(CacheConstants.USER_DETAILS_MINI).evict(appUserInfo.getPhone());
return Boolean.TRUE;
}
/**
* 新增用户
* @param userDTO
* @return
* @param userDTO 用户数据传输对象
* @return 保存结果
*/
@Override
public Boolean saveUser(AppUserDTO userDTO) {
// 创建用户实体并复制属性
AppUser appUser = new AppUser();
BeanUtils.copyProperties(userDTO, appUser);
// 设置删除标志为正常状态
appUser.setDelFlag(CommonConstants.STATUS_NORMAL);
// 对密码进行加密
appUser.setPassword(ENCODER.encode(userDTO.getPassword()));
// 插入用户记录
baseMapper.insert(appUser);
// 如果角色为空,赋默认角色
// 如果角色列表不为空,建立用户与角色的关联关系
if (CollUtil.isNotEmpty(userDTO.getRole())) {
List<AppUserRole> userRoleList = userDTO.getRole().stream().map(roleId -> {
AppUserRole userRole = new AppUserRole();
userRole.setUserId(appUser.getUserId());
userRole.setRoleId(roleId);
return userRole;
}).collect(Collectors.toList());
}).toList();
// 批量保存用户角色关联
appUserRoleService.saveBatch(userRoleList);
}
return Boolean.TRUE;
}
/**
* 查询全部的用户
* @param appUser
* @return
* 查询全部用户(用于Excel导出)
* @param appUser 查询条件
* @return 用户Excel视图对象列表
*/
@Override
public List<AppUserExcelVO> listUser(AppUserDTO appUser) {
// 查询所有用户
List<AppUser> appUsers = baseMapper.selectList(null);
// 将用户实体转换为Excel视图对象
List<AppUserExcelVO> appUserExcelVOS = appUsers.stream().map(item -> {
AppUserExcelVO appUserExcelVO = new AppUserExcelVO();
BeanUtils.copyProperties(item, appUserExcelVO);
return appUserExcelVO;
}).collect(Collectors.toList());
}).toList();
return appUserExcelVOS;
}
/**
* 分页查询用户(包含角色信息)
* @param page 分页参数
* @param appUserDTO 查询条件
* @return 分页结果
*/
@Override
public IPage getUsersWithRolePage(Page page, AppUserDTO appUserDTO) {
return baseMapper.getUserVosPage(page, appUserDTO);
}
/**
* 查询用户详细信息(包含角色和权限)
* @param user 用户对象
* @return 用户信息对象
*/
@Override
public AppUserInfo findUserInfo(AppUser user) {
// 创建用户信息对象
AppUserInfo info = new AppUserInfo();
info.setAppUser(user);
// 设置角色列表 (ID)
// 设置角色列表(ID数组)
List<Long> roleIds = appRoleService.findRolesByUserId(user.getUserId())
.stream()
.map(AppRole::getRoleId)
.collect(Collectors.toList());
.toList();
info.setRoles(ArrayUtil.toArray(roleIds, Long.class));
// 设置权限列表(menu.permission)
// 设置权限列表(暂为空)
Set<String> permissions = new HashSet<>();
info.setPermissions(ArrayUtil.toArray(permissions, String.class));
return info;
}
/**
* 更新用户个人信息
* @param userDTO 用户数据传输对象
* @return 操作结果
*/
@Override
@CacheEvict(value = CacheConstants.USER_DETAILS_MINI, key = "#userDto.username")
public R updateUserInfo(AppUserDTO userDto) {
// C端客户修改手机号需要判断验证码是否正确
@CacheEvict(value = CacheConstants.USER_DETAILS_MINI, key = "#userDTO.username")
public R updateUserInfo(AppUserDTO userDTO) {
// 获取当前登录用户
PigxUser user = SecurityUtils.getUser();
if (UserTypeEnum.TOC.getStatus().equals(user.getUserType()) && StrUtil.isNotBlank(userDto.getPhone())) {
String key = CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.APPSMS.getType() + StringPool.AT
+ userDto.getPhone();
String codeObj = redisTemplate.opsForValue().get(key);
if (!userDto.getMobileCode().equals(codeObj)) {
// C端客户修改手机号需要验证短信验证码
if (UserTypeEnum.TOC.getStatus().equals(user.getUserType()) && StrUtil.isNotBlank(userDTO.getPhone())) {
// 构建验证码缓存key
String key = CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.APPSMS.getType() + StringPool.AT
+ userDTO.getPhone();
// 获取缓存中的验证码
String codeObj = RedisUtils.get(key);
// 验证码不匹配,返回错误
if (!userDTO.getMobileCode().equals(codeObj)) {
return R.failed("验证码错误");
}
}
// 更新密码
if (StrUtil.isNotBlank(userDto.getPassword())) {
userDto.setPassword(ENCODER.encode(userDto.getPassword()));
// 更新密码(如果提供了新密码)
if (StrUtil.isNotBlank(userDTO.getPassword())) {
userDTO.setPassword(ENCODER.encode(userDTO.getPassword()));
}
AppUser appUser = baseMapper.selectById(userDto.getUserId());
BeanUtils.copyProperties(userDto, appUser);
// 获取原用户信息并更新
AppUser appUser = baseMapper.selectById(userDTO.getUserId());
BeanUtils.copyProperties(userDTO, appUser);
// 清除以手机号为key的用户缓存
cacheManager.getCache(CacheConstants.USER_DETAILS_MINI).evict(user.getPhone());
return R.ok(this.updateById(appUser));
}
/**
* 根据用户ID查询用户视图对象
* @param userId 用户ID
* @return 用户视图对象
*/
@Override
public AppUserVO selectUserVoById(Long userId) {
return baseMapper.getUserVoById(userId);
}
/**
* 删除user用户同时删除user-role关系表
* @param ids userIds
* 批量删除用户
* @param ids 用户ID数组
* @return 删除结果
*/
@Override
public Boolean deleteAppUserByIds(Long[] ids) {
// 获取缓存对象
Cache cache = cacheManager.getCache(CacheConstants.USER_DETAILS_MINI);
// 清除用户缓存
for (AppUser appUser : baseMapper.selectByIds(CollUtil.toList(ids))) {
cache.evict(appUser.getUsername());
}
// 删除用户关联表
// 删除用户角色关联关系
this.appUserRoleService
.remove(Wrappers.<AppUserRole>lambdaQuery().in(AppUserRole::getUserId, CollUtil.toList(ids)));
// 删除用户记录
this.removeBatchByIds(CollUtil.toList(ids));
return Boolean.TRUE;
}
/**
* 注册APP用户
* @param appUser 用户数据传输对象
* @return 操作结果
*/
@Override
public R registerAppUser(AppUserDTO appUser) {
// 检查手机号是否已被注册
List<AppUser> appUserList = baseMapper
.selectList(Wrappers.<AppUser>lambdaQuery().eq(AppUser::getPhone, appUser.getPhone()));
@@ -230,17 +300,19 @@ public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> impl
return R.failed("手机号已注册,请使用验证码直接登录");
}
// 验证短信验证码
String key = CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.APPSMS.getType() + StringPool.AT
+ appUser.getPhone();
String codeObj = redisTemplate.opsForValue().get(key);
String codeObj = RedisUtils.get(key);
if (!appUser.getMobileCode().equals(codeObj)) {
return R.failed("验证码错误");
}
// 创建用户并保存
AppUser app = new AppUser();
BeanUtils.copyProperties(appUser, app);
appUser.setUsername(app.getPhone());
appUser.setUsername(app.getPhone()); // 默认使用手机号作为用户名
appUser.setDelFlag(CommonConstants.STATUS_NORMAL);
appUser.setPassword(ENCODER.encode(appUser.getPassword()));
baseMapper.insert(appUser);
@@ -248,23 +320,25 @@ public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> impl
}
/**
* @param excelVOList
* @param bindingResult
* @return
* 导入用户(从Excel导入)
* @param excelVOList Excel数据列表
* @param bindingResult 数据校验结果
* @return 导入结果
*/
@Override
public R importUser(List<AppUserExcelVO> excelVOList, BindingResult bindingResult) {
// 通用校验获取失败的数据
// 获取通用校验失败的数据
List<ErrorMessage> errorMessageList = (List<ErrorMessage>) bindingResult.getTarget();
// 执行数据插入操作 组装 UserDto
for (AppUserExcelVO excel : excelVOList) {
// 个性化校验逻辑
List<AppUser> userList = this.list();
List<AppRole> roleList = appRoleService.list();
// 获取现有用户和角色列表,用于校验
List<AppUser> userList = this.list();
List<AppRole> roleList = appRoleService.list();
// 遍历Excel数据进行处理
for (AppUserExcelVO excel : excelVOList) {
Set<String> errorMsg = new HashSet<>();
// 校验用户名是否存在
// 校验用户名是否已存在
boolean exsitUserName = userList.stream()
.anyMatch(sysUser -> excel.getUsername().equals(sysUser.getUsername()));
@@ -272,47 +346,54 @@ public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> impl
errorMsg.add(MsgUtils.getMessage(ErrorCodes.SYS_USER_USERNAME_EXISTING, excel.getUsername()));
}
// 判断输入的角色名称列表是否合法
// 校验角色名称是否合法
List<String> roleNameList = StrUtil.split(excel.getRoleNameList(), StrUtil.COMMA);
List<AppRole> roleCollList = roleList.stream()
.filter(role -> roleNameList.stream().anyMatch(name -> role.getRoleName().equals(name)))
.collect(Collectors.toList());
.toList();
if (roleCollList.size() != roleNameList.size()) {
errorMsg.add(MsgUtils.getMessage(ErrorCodes.SYS_ROLE_ROLENAME_INEXISTENCE, excel.getRoleNameList()));
}
// 数据合法情况
// 数据合法时执行插入
if (CollUtil.isEmpty(errorMsg)) {
insertExcelUser(excel, roleCollList);
}
else {
// 数据不合法情况
// 记录不合法数据的错误信息
errorMessageList.add(new ErrorMessage(excel.getLineNum(), errorMsg));
}
}
// 存在错误信息时返回失败
if (CollUtil.isNotEmpty(errorMessageList)) {
return R.failed(errorMessageList);
}
return R.ok(null, MsgUtils.getMessage(ErrorCodes.SYS_USER_IMPORT_SUCCEED));
}
/**
* 插入Excel导入的用户数据
* @param excel Excel用户数据
* @param roleCollList 角色列表
*/
private void insertExcelUser(AppUserExcelVO excel, List<AppRole> roleCollList) {
// 创建用户DTO并设置基本信息
AppUserDTO userDTO = new AppUserDTO();
userDTO.setUsername(excel.getUsername());
userDTO.setPhone(excel.getPhone());
userDTO.setNickname(excel.getNickname());
userDTO.setName(excel.getName());
userDTO.setEmail(excel.getEmail());
// 批量导入初始密码为手机号
// 批量导入时初始密码设置为手机号
userDTO.setPassword(userDTO.getPhone());
// 根据角色名称查询角色ID
List<Long> roleIdList = roleCollList.stream().map(AppRole::getRoleId).collect(Collectors.toList());
// 获取角色ID列表
List<Long> roleIdList = roleCollList.stream().map(AppRole::getRoleId).toList();
userDTO.setRole(roleIdList);
// 插入用户
// 保存用户
this.saveUser(userDTO);
}
}
@@ -1,10 +1,7 @@
package com.pig4cloud.pigx.auth.endpoint;
import com.anji.captcha.service.CaptchaCacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.concurrent.TimeUnit;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
/**
* @author lengleng
@@ -16,27 +13,24 @@ public class CaptchaCacheServiceProvider implements CaptchaCacheService {
private static final String REDIS = "redis";
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public void set(String key, String value, long expiresInSeconds) {
stringRedisTemplate.opsForValue().set(key, value, expiresInSeconds, TimeUnit.SECONDS);
RedisUtils.set(key, value, expiresInSeconds);
}
@Override
public boolean exists(String key) {
return stringRedisTemplate.hasKey(key);
return RedisUtils.hasKey(key);
}
@Override
public void delete(String key) {
stringRedisTemplate.delete(key);
RedisUtils.delete(key);
}
@Override
public String get(String key) {
return stringRedisTemplate.opsForValue().get(key);
return RedisUtils.get(key);
}
@Override
@@ -8,19 +8,17 @@ import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.core.util.SpringContextHolder;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import io.springboot.captcha.ArithmeticCaptcha;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
/**
* 验证码相关的接口
*
@@ -36,8 +34,6 @@ public class ImageCodeEndpoint {
private static final Integer DEFAULT_IMAGE_HEIGHT = 40;
private final StringRedisTemplate redisTemplate;
/**
* 创建图形验证码
*/
@@ -53,8 +49,7 @@ public class ImageCodeEndpoint {
return;
}
redisTemplate.opsForValue()
.set(CacheConstants.DEFAULT_CODE_KEY + randomStr, result, SecurityConstants.CODE_TIME, TimeUnit.SECONDS);
RedisUtils.set(CacheConstants.DEFAULT_CODE_KEY + randomStr, result, SecurityConstants.CODE_TIME);
// 转换流信息写出
captcha.out(response.getOutputStream());
}
@@ -32,6 +32,7 @@ import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.core.util.RetOps;
import com.pig4cloud.pigx.common.core.util.SpringContextHolder;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder;
import com.pig4cloud.pigx.common.security.annotation.Inner;
import com.pig4cloud.pigx.common.security.util.OAuth2ErrorCodesExpand;
@@ -42,7 +43,6 @@ import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.CacheManager;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.ServletServerHttpResponse;
@@ -77,8 +77,6 @@ public class PigxTokenEndpoint {
private final RemoteClientDetailsService clientDetailsService;
private final RedisTemplate<String, Object> redisTemplate;
private final RemoteTenantService tenantService;
private final CacheManager cacheManager;
@@ -213,7 +211,7 @@ public class PigxTokenEndpoint {
// 根据是否有username参数选择不同的查询key
String searchKey = StrUtil.isNotBlank(username) ? usernameKey : key;
Set<String> keys = redisTemplate.keys(searchKey);
Set<String> keys = RedisUtils.keys(searchKey);
// 分页处理
List<String> pages = keys.stream().skip((current - 1) * size).limit(size).toList();
@@ -234,7 +232,7 @@ public class PigxTokenEndpoint {
tokenVo.setId(keyParts[5]);
tokenVo.setAccessToken(keyParts[5]);
// 获取TTL作为过期时间
Long ttl = redisTemplate.getExpire(keyName);
Long ttl = RedisUtils.getExpire(keyName);
// TTL是秒数,转换为过期时间
long expiresAtMillis = System.currentTimeMillis() + (ttl * 1000);
String expiresAt = TemporalAccessorUtil.format(java.time.Instant.ofEpochMilli(expiresAtMillis), DatePattern.NORM_DATETIME_PATTERN);
@@ -2,8 +2,8 @@ package com.pig4cloud.pigx.auth.support.base;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.pig4cloud.pigx.auth.support.store.PigxRedisOAuth2AuthorizationService;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.security.service.PigxRedisOAuth2AuthorizationService;
import com.pig4cloud.pigx.common.security.util.OAuth2ErrorCodesExpand;
import com.pig4cloud.pigx.common.security.util.ScopeException;
import lombok.extern.slf4j.Slf4j;
@@ -30,13 +30,13 @@ import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.constant.enums.EncFlagTypeEnum;
import com.pig4cloud.pigx.common.core.util.RepeatBodyRequestWrapper;
import com.pig4cloud.pigx.common.core.util.WebUtils;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
@@ -55,85 +55,83 @@ import java.util.Map;
@RequiredArgsConstructor
public class PasswordDecoderFilter extends OncePerRequestFilter {
private final AuthSecurityConfigProperties authSecurityConfigProperties;
private static final String PASSWORD = "password";
private static final String KEY_ALGORITHM = "AES";
private final StringRedisTemplate redisTemplate;
static {
// 关闭hutool 强制关闭Bouncy Castle库的依赖
SecureUtil.disableBouncyCastle();
}
private static final String PASSWORD = "password";
private final AuthSecurityConfigProperties authSecurityConfigProperties;
private static final String KEY_ALGORITHM = "AES";
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
// 不是登录请求,直接向下执行
if (!StrUtil.containsAnyIgnoreCase(request.getRequestURI(), SecurityConstants.OAUTH_TOKEN_URL)) {
chain.doFilter(request, response);
return;
}
static {
// 关闭hutool 强制关闭Bouncy Castle库的依赖
SecureUtil.disableBouncyCastle();
}
// 2. 刷新token类型,直接向下执行
String grantType = request.getParameter("grant_type");
if (StrUtil.equals(SecurityConstants.REFRESH_TOKEN, grantType)) {
chain.doFilter(request, response);
return;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
// 不是登录请求,直接向下执行
if (!StrUtil.containsAnyIgnoreCase(request.getRequestURI(), SecurityConstants.OAUTH_TOKEN_URL)) {
chain.doFilter(request, response);
return;
}
// 3. 判断客户端是否需要解密,明文传输直接向下执行
if (!isEncClient(request)) {
chain.doFilter(request, response);
return;
}
// 2. 刷新token类型,直接向下执行
String grantType = request.getParameter("grant_type");
if (StrUtil.equals(SecurityConstants.REFRESH_TOKEN, grantType)) {
chain.doFilter(request, response);
return;
}
// 将请求流转换为可多次读取的请求流
RepeatBodyRequestWrapper requestWrapper = new RepeatBodyRequestWrapper(request);
Map<String, String[]> parameterMap = requestWrapper.getParameterMap();
// 3. 判断客户端是否需要解密,明文传输直接向下执行
if (!isEncClient(request)) {
chain.doFilter(request, response);
return; }
// 构建前端对应解密AES 因子
AES aes = new AES(Mode.CFB, Padding.NoPadding,
new SecretKeySpec(authSecurityConfigProperties.getEncodeKey().getBytes(), KEY_ALGORITHM),
new IvParameterSpec(authSecurityConfigProperties.getEncodeKey().getBytes()));
// 将请求流转换为可多次读取的请求流
RepeatBodyRequestWrapper requestWrapper = new RepeatBodyRequestWrapper(request);
Map<String, String[]> parameterMap = requestWrapper.getParameterMap();
parameterMap.forEach((k, v) -> {
String[] values = parameterMap.get(k);
if (!PASSWORD.equals(k) || ArrayUtil.isEmpty(values)) {
return;
}
// 构建前端对应解密AES 因子
AES aes = new AES(Mode.CFB, Padding.NoPadding,
new SecretKeySpec(authSecurityConfigProperties.getEncodeKey().getBytes(), KEY_ALGORITHM),
new IvParameterSpec(authSecurityConfigProperties.getEncodeKey().getBytes()));
// 解密密码
String decryptPassword = aes.decryptStr(values[0]);
parameterMap.put(k, new String[]{decryptPassword});
});
chain.doFilter(requestWrapper, response);
}
parameterMap.forEach((k, v) -> {
String[] values = parameterMap.get(k);
if (!PASSWORD.equals(k) || ArrayUtil.isEmpty(values)) {
return;
}
/**
* 根据请求的clientId 查询客户端配置是否是加密传输
*
* @param request 请求上下文
* @return true 加密传输 、 false 原文传输
*/
private boolean isEncClient(HttpServletRequest request) {
String header = request.getHeader(HttpHeaders.AUTHORIZATION);
String clientId = WebUtils.extractClientId(header).orElse(null);
// 获取租户拼接区分租户的key
String tenantId = request.getHeader(CommonConstants.TENANT_ID);
String key = String.format("%s:%s:%s", StrUtil.isBlank(tenantId) ? CommonConstants.TENANT_ID_1 : tenantId,
CacheConstants.CLIENT_FLAG, clientId);
// 解密密码
String decryptPassword = aes.decryptStr(values[0]);
parameterMap.put(k, new String[]{decryptPassword});
});
chain.doFilter(requestWrapper, response);
}
String val = RedisUtils.get(key);
/**
* 根据请求的clientId 查询客户端配置是否是加密传输
*
* @param request 请求上下文
* @return true 加密传输 、 false 原文传输
*/
private boolean isEncClient(HttpServletRequest request) {
String header = request.getHeader(HttpHeaders.AUTHORIZATION);
String clientId = WebUtils.extractClientId(header).orElse(null);
// 获取租户拼接区分租户的key
String tenantId = request.getHeader(CommonConstants.TENANT_ID);
String key = String.format("%s:%s:%s", StrUtil.isBlank(tenantId) ? CommonConstants.TENANT_ID_1 : tenantId,
CacheConstants.CLIENT_FLAG, clientId);
// 当配置不存在时,默认需要解密
if (val == null) {
return true;
}
String val = redisTemplate.opsForValue().get(key);
// 当配置不存在时,默认需要解密
if (val == null) {
return true;
}
JSONObject information = JSONUtil.parseObj(val);
return !StrUtil.equals(EncFlagTypeEnum.NO.getType(), information.getStr(CommonConstants.ENC_FLAG));
}
JSONObject information = JSONUtil.parseObj(val);
return !StrUtil.equals(EncFlagTypeEnum.NO.getType(), information.getStr(CommonConstants.ENC_FLAG));
}
}
@@ -19,13 +19,13 @@ import com.pig4cloud.pigx.common.core.constant.enums.CaptchaFlagTypeEnum;
import com.pig4cloud.pigx.common.core.exception.ValidateCodeException;
import com.pig4cloud.pigx.common.core.util.SpringContextHolder;
import com.pig4cloud.pigx.common.core.util.WebUtils;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
@@ -45,135 +45,131 @@ import java.io.IOException;
@RequiredArgsConstructor
public class ValidateCodeFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
private final StringRedisTemplate redisTemplate;
String requestUrl = request.getServletPath();
// 不是登录URL 请求直接跳过
if (!SecurityConstants.OAUTH_TOKEN_URL.equals(requestUrl)) {
filterChain.doFilter(request, response);
return;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// 如果登录URL 但是刷新token的请求,直接向下执行
String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
if (StrUtil.containsAny(grantType, SecurityConstants.REFRESH_TOKEN)) {
filterChain.doFilter(request, response);
return;
}
String requestUrl = request.getServletPath();
// mobile模式, 如果请求不包含mobile 参数直接
String mobile = request.getParameter(SecurityConstants.GRANT_MOBILE);
if (StrUtil.equals(SecurityConstants.GRANT_MOBILE, grantType) && StrUtil.isBlank(mobile)) {
throw new OAuth2AuthenticationException(SecurityConstants.GRANT_MOBILE);
}
// 不是登录URL 请求直接跳过
if (!SecurityConstants.OAUTH_TOKEN_URL.equals(requestUrl)) {
filterChain.doFilter(request, response);
return;
}
// mobile模式, 社交登录模式不校验验证码直接跳过
if (StrUtil.equals(SecurityConstants.GRANT_MOBILE, grantType) && !StrUtil.contains(mobile, "SMS")) {
filterChain.doFilter(request, response);
return;
}
// 如果登录URL 但是刷新token的请求,直接向下执行
String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
if (StrUtil.containsAny(grantType, SecurityConstants.REFRESH_TOKEN)) {
filterChain.doFilter(request, response);
return;
}
// 判断客户端是否跳过检验
if (!isCheckCaptchaClient(request)) {
filterChain.doFilter(request, response);
return;
}
// mobile模式, 如果请求不包含mobile 参数直接
String mobile = request.getParameter(SecurityConstants.GRANT_MOBILE);
if (StrUtil.equals(SecurityConstants.GRANT_MOBILE, grantType) && StrUtil.isBlank(mobile)) {
throw new OAuth2AuthenticationException(SecurityConstants.GRANT_MOBILE);
}
// 校验验证码 1. 客户端开启验证码 2. 短信模式
try {
checkCode();
filterChain.doFilter(request, response);
} catch (ValidateCodeException validateCodeException) {
throw new OAuth2AuthenticationException(validateCodeException.getMessage());
}
}
// mobile模式, 社交登录模式不校验验证码直接跳过
if (StrUtil.equals(SecurityConstants.GRANT_MOBILE, grantType) && !StrUtil.contains(mobile, "SMS")) {
filterChain.doFilter(request, response);
return;
}
/**
* 校验验证码
*/
private void checkCode() throws ValidateCodeException {
HttpServletRequest request = WebUtils.getRequest();
String code = request.getParameter("code");
// 判断客户端是否跳过检验
if (!isCheckCaptchaClient(request)) {
filterChain.doFilter(request, response);
return;
}
if (StrUtil.isBlank(code)) {
throw new ValidateCodeException("验证码不能为空");
}
// 校验验证码 1. 客户端开启验证码 2. 短信模式
try {
checkCode();
filterChain.doFilter(request, response);
} catch (ValidateCodeException validateCodeException) {
throw new OAuth2AuthenticationException(validateCodeException.getMessage());
}
}
String randomStr = request.getParameter("randomStr");
/**
* 校验验证码
*/
private void checkCode() throws ValidateCodeException {
HttpServletRequest request = WebUtils.getRequest();
String code = request.getParameter("code");
// https://gitee.com/log4j/pig/issues/IWA0D
String mobile = request.getParameter("mobile");
if (StrUtil.isNotBlank(mobile)) {
randomStr = mobile;
}
if (StrUtil.isBlank(code)) {
throw new ValidateCodeException("验证码不能为空");
}
// 若是滑块登录
if (CommonConstants.IMAGE_CODE_TYPE.equalsIgnoreCase(randomStr)) {
CaptchaService captchaService = SpringContextHolder.getBean(CaptchaService.class);
CaptchaVO vo = new CaptchaVO();
vo.setCaptchaVerification(code);
vo.setCaptchaType(CommonConstants.IMAGE_CODE_TYPE);
if (!captchaService.verification(vo).isSuccess()) {
throw new ValidateCodeException("验证码不能为空");
}
return;
}
String randomStr = request.getParameter("randomStr");
String key = CacheConstants.DEFAULT_CODE_KEY + randomStr;
if (!RedisUtils.hasKey(key)) {
throw new ValidateCodeException("验证码不合法");
}
// https://gitee.com/log4j/pig/issues/IWA0D
String mobile = request.getParameter("mobile");
if (StrUtil.isNotBlank(mobile)) {
randomStr = mobile;
}
String codeObj = RedisUtils.get(key);
// 若是滑块登录
if (CommonConstants.IMAGE_CODE_TYPE.equalsIgnoreCase(randomStr)) {
CaptchaService captchaService = SpringContextHolder.getBean(CaptchaService.class);
CaptchaVO vo = new CaptchaVO();
vo.setCaptchaVerification(code);
vo.setCaptchaType(CommonConstants.IMAGE_CODE_TYPE);
if (!captchaService.verification(vo).isSuccess()) {
throw new ValidateCodeException("验证码不能为空");
}
return;
}
if (codeObj == null) {
throw new ValidateCodeException("验证码不合法");
}
String saveCode = codeObj;
if (StrUtil.isBlank(saveCode)) {
RedisUtils.delete(key);
throw new ValidateCodeException("验证码不合法");
}
String key = CacheConstants.DEFAULT_CODE_KEY + randomStr;
if (Boolean.FALSE.equals(redisTemplate.hasKey(key))) {
throw new ValidateCodeException("验证码不合法");
}
if (!StrUtil.equals(saveCode, code)) {
RedisUtils.delete(key);
throw new ValidateCodeException("验证码不合法");
}
Object codeObj = redisTemplate.opsForValue().get(key);
RedisUtils.delete(key);
}
if (codeObj == null) {
throw new ValidateCodeException("验证码不合法");
}
/**
* 是否需要校验客户端,根据client 查询客户端配置
*
* @param request 请求
* @return true 需要校验, false 不需要校验
*/
private boolean isCheckCaptchaClient(HttpServletRequest request) {
String header = request.getHeader(HttpHeaders.AUTHORIZATION);
String clientId = WebUtils.extractClientId(header).orElse(null);
// 获取租户拼接区分租户的key
String tenantId = request.getHeader(CommonConstants.TENANT_ID);
String key = String.format("%s:%s:%s", StrUtil.isBlank(tenantId) ? CommonConstants.TENANT_ID_1 : tenantId,
CacheConstants.CLIENT_FLAG, clientId);
String saveCode = codeObj.toString();
if (StrUtil.isBlank(saveCode)) {
redisTemplate.delete(key);
throw new ValidateCodeException("验证码不合法");
}
String val = RedisUtils.get(key);
if (!StrUtil.equals(saveCode, code)) {
redisTemplate.delete(key);
throw new ValidateCodeException("验证码不合法");
}
// 当配置不存在时,不用校验
if (val == null) {
return false;
}
redisTemplate.delete(key);
}
JSONObject information = JSONUtil.parseObj(val);
return !StrUtil.equals(CaptchaFlagTypeEnum.OFF.getType(), information.getStr(CommonConstants.CAPTCHA_FLAG));
}
/**
* 是否需要校验客户端,根据client 查询客户端配置
*
* @param request 请求
* @return true 需要校验, false 不需要校验
*/
private boolean isCheckCaptchaClient(HttpServletRequest request) {
String header = request.getHeader(HttpHeaders.AUTHORIZATION);
String clientId = WebUtils.extractClientId(header).orElse(null);
// 获取租户拼接区分租户的key
String tenantId = request.getHeader(CommonConstants.TENANT_ID);
String key = String.format("%s:%s:%s", StrUtil.isBlank(tenantId) ? CommonConstants.TENANT_ID_1 : tenantId,
CacheConstants.CLIENT_FLAG, clientId);
String val = redisTemplate.opsForValue().get(key);
// 当配置不存在时,不用校验
if (val == null) {
return false;
}
JSONObject information = JSONUtil.parseObj(val);
return !StrUtil.equals(CaptchaFlagTypeEnum.OFF.getType(), information.getStr(CommonConstants.CAPTCHA_FLAG));
}
}
@@ -25,6 +25,7 @@ import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.util.KeyStrResolver;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.core.util.WebUtils;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import com.pig4cloud.pigx.common.data.resolver.ParamResolver;
import com.pig4cloud.pigx.common.log.event.SysLogEvent;
import com.pig4cloud.pigx.common.log.util.LogTypeEnum;
@@ -35,7 +36,7 @@ import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
@@ -48,7 +49,6 @@ import org.springframework.security.web.authentication.AuthenticationFailureHand
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
* @author lengleng
@@ -61,8 +61,6 @@ public class PigxAuthenticationFailureEventHandler implements AuthenticationFail
private static final MappingJackson2HttpMessageConverter errorHttpResponseConverter = new MappingJackson2HttpMessageConverter();
private final StringRedisTemplate redisTemplate;
private final ApplicationEventPublisher publisher;
private final KeyStrResolver tenantKeyStrResolver;
@@ -135,11 +133,15 @@ public class PigxAuthenticationFailureEventHandler implements AuthenticationFail
private void recordLoginFailureTimes(String username) {
String key = String.format("%s:%s:%s", tenantKeyStrResolver.key(), CacheConstants.LOGIN_ERROR_TIMES, username);
Long deltaTimes = ParamResolver.getLong("LOGIN_ERROR_TIMES", 5L);
Long times = redisTemplate.opsForValue().increment(key);
// 使用 RedisUtils 执行原生 Redis 命令进行递增操作
Long times = RedisUtils.execute((RedisCallback<Long>) connection ->
connection.incr(key.getBytes())
);
// 自动过期时间
Long deltaTime = ParamResolver.getLong("DELTA_TIME", 1L);
redisTemplate.expire(key, deltaTime, TimeUnit.HOURS);
RedisUtils.expire(key, deltaTime * 3600); // 转换为秒
if (deltaTimes <= times) {
userService.lockUser(username);
@@ -23,6 +23,7 @@ import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.util.KeyStrResolver;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import com.pig4cloud.pigx.common.log.event.SysLogEvent;
import com.pig4cloud.pigx.common.log.util.LogTypeEnum;
import com.pig4cloud.pigx.common.log.util.SysLogUtils;
@@ -32,7 +33,6 @@ import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.security.core.Authentication;
@@ -62,8 +62,6 @@ public class PigxAuthenticationSuccessEventHandler implements AuthenticationSucc
private static final HttpMessageConverter<OAuth2AccessTokenResponse> accessTokenHttpResponseConverter = new OAuth2AccessTokenResponseHttpMessageConverter();
private final StringRedisTemplate redisTemplate;
private final ApplicationEventPublisher publisher;
private final KeyStrResolver tenantKeyStrResolver;
@@ -132,7 +130,7 @@ public class PigxAuthenticationSuccessEventHandler implements AuthenticationSucc
private void clearLoginFailureTimes(Map<String, Object> map) {
String key = String.format("%s:%s:%s", tenantKeyStrResolver.key(), CacheConstants.LOGIN_ERROR_TIMES,
MapUtil.getStr(map, SecurityConstants.DETAILS_USERNAME));
redisTemplate.delete(key);
RedisUtils.delete(key);
}
private void sendAccessTokenResponse(HttpServletResponse response, Authentication authentication)
@@ -1,41 +1,37 @@
package com.pig4cloud.pigx.common.security.service;
package com.pig4cloud.pigx.auth.support.store;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsent;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.util.concurrent.TimeUnit;
@Service
@RequiredArgsConstructor
public class PigxRedisOAuth2AuthorizationConsentService implements OAuth2AuthorizationConsentService {
private final RedisTemplate<String, Object> redisTemplate;
private final static Long TIMEOUT = 10L;
@Override
public void save(OAuth2AuthorizationConsent authorizationConsent) {
Assert.notNull(authorizationConsent, "authorizationConsent cannot be null");
redisTemplate.opsForValue()
.set(buildKey(authorizationConsent), authorizationConsent, TIMEOUT, TimeUnit.MINUTES);
RedisUtils.set(buildKey(authorizationConsent), authorizationConsent, TIMEOUT * 60);
}
@Override
public void remove(OAuth2AuthorizationConsent authorizationConsent) {
Assert.notNull(authorizationConsent, "authorizationConsent cannot be null");
redisTemplate.delete(buildKey(authorizationConsent));
RedisUtils.delete(buildKey(authorizationConsent));
}
@Override
public OAuth2AuthorizationConsent findById(String registeredClientId, String principalName) {
Assert.hasText(registeredClientId, "registeredClientId cannot be empty");
Assert.hasText(principalName, "principalName cannot be empty");
return (OAuth2AuthorizationConsent) redisTemplate.opsForValue()
.get(buildKey(registeredClientId, principalName));
return RedisUtils.get(buildKey(registeredClientId, principalName));
}
private static String buildKey(String registeredClientId, String principalName) {
@@ -1,10 +1,10 @@
package com.pig4cloud.pigx.common.security.service;
package com.pig4cloud.pigx.auth.support.store;
import cn.hutool.core.collection.CollUtil;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import com.pig4cloud.pigx.common.security.service.PigxUser;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.lang.Nullable;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
@@ -15,6 +15,7 @@ import org.springframework.security.oauth2.server.authorization.OAuth2Authorizat
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationCode;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.security.Principal;
@@ -23,12 +24,14 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* 基于Redis实现的OAuth2授权服务类,提供授权信息的存储、查询和删除功能
*
* @author lengleng
* @date 2022/5/27
* @date 2025/06/30
*/
@Service
@RequiredArgsConstructor
public class PigxRedisOAuth2AuthorizationService implements OAuth2AuthorizationService {
@@ -36,8 +39,6 @@ public class PigxRedisOAuth2AuthorizationService implements OAuth2AuthorizationS
private static final String AUTHORIZATION = "token";
private final RedisTemplate<String, Object> redisTemplate;
private static boolean isState(OAuth2Authorization authorization) {
return Objects.nonNull(authorization.getAttribute("state"));
}
@@ -62,9 +63,7 @@ public class PigxRedisOAuth2AuthorizationService implements OAuth2AuthorizationS
if (isState(authorization)) {
String token = authorization.getAttribute("state");
redisTemplate.setValueSerializer(RedisSerializer.java());
redisTemplate.opsForValue()
.set(buildKey(OAuth2ParameterNames.STATE, token), authorization, TIMEOUT, TimeUnit.MINUTES);
RedisUtils.set(buildKey(OAuth2ParameterNames.STATE, token), authorization, TIMEOUT * 60);
}
if (isCode(authorization)) {
@@ -73,28 +72,20 @@ public class PigxRedisOAuth2AuthorizationService implements OAuth2AuthorizationS
OAuth2AuthorizationCode authorizationCodeToken = authorizationCode.getToken();
long between = ChronoUnit.MINUTES.between(authorizationCodeToken.getIssuedAt(),
authorizationCodeToken.getExpiresAt());
redisTemplate.setValueSerializer(RedisSerializer.java());
redisTemplate.opsForValue()
.set(buildKey(OAuth2ParameterNames.CODE, authorizationCodeToken.getTokenValue()), authorization,
between, TimeUnit.MINUTES);
RedisUtils.set(buildKey(OAuth2ParameterNames.CODE, authorizationCodeToken.getTokenValue()), authorization,
(int) (between * 60));
}
if (isRefreshToken(authorization)) {
OAuth2RefreshToken refreshToken = authorization.getRefreshToken().getToken();
long between = ChronoUnit.SECONDS.between(refreshToken.getIssuedAt(), refreshToken.getExpiresAt());
redisTemplate.setValueSerializer(RedisSerializer.java());
redisTemplate.opsForValue()
.set(buildKey(OAuth2ParameterNames.REFRESH_TOKEN, refreshToken.getTokenValue()), authorization, between,
TimeUnit.SECONDS);
RedisUtils.set(buildKey(OAuth2ParameterNames.REFRESH_TOKEN, refreshToken.getTokenValue()), authorization, (int) between);
}
if (isAccessToken(authorization)) {
OAuth2AccessToken accessToken = authorization.getAccessToken().getToken();
long between = ChronoUnit.SECONDS.between(accessToken.getIssuedAt(), accessToken.getExpiresAt());
redisTemplate.setValueSerializer(RedisSerializer.java());
redisTemplate.opsForValue()
.set(buildKey(OAuth2ParameterNames.ACCESS_TOKEN, accessToken.getTokenValue()), authorization, between,
TimeUnit.SECONDS);
RedisUtils.set(buildKey(OAuth2ParameterNames.ACCESS_TOKEN, accessToken.getTokenValue()), authorization, (int) between);
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = authorization.getAttribute(Principal.class.getName());
@@ -102,7 +93,7 @@ public class PigxRedisOAuth2AuthorizationService implements OAuth2AuthorizationS
// 扩展记录 access-token 、username 的关系 token::username::admin::tenantId::xxx
String tokenUsername = String.format("%s::%s::%s::%s::%s::%s", AUTHORIZATION,
SecurityConstants.DETAILS_USERNAME, authorization.getPrincipalName(), authorization.getRegisteredClientId(), pigxUser.getTenantId(), accessToken.getTokenValue());
redisTemplate.opsForValue().set(tokenUsername, accessToken.getTokenValue(), between, TimeUnit.SECONDS);
RedisUtils.set(tokenUsername, accessToken.getTokenValue(), (int) between);
}
}
}
@@ -139,7 +130,7 @@ public class PigxRedisOAuth2AuthorizationService implements OAuth2AuthorizationS
keys.add(key);
}
redisTemplate.delete(keys);
RedisUtils.delete(keys.toArray(new String[0]));
}
@Override
@@ -152,9 +143,7 @@ public class PigxRedisOAuth2AuthorizationService implements OAuth2AuthorizationS
@Nullable
public OAuth2Authorization findByToken(String token, @Nullable OAuth2TokenType tokenType) {
Assert.hasText(token, "token cannot be empty");
redisTemplate.setValueSerializer(RedisSerializer.java());
return (OAuth2Authorization) redisTemplate.opsForValue()
.get(buildKey(Objects.requireNonNullElse(tokenType, OAuth2TokenType.ACCESS_TOKEN).getValue(), token));
return RedisUtils.get(buildKey(Objects.requireNonNullElse(tokenType, OAuth2TokenType.ACCESS_TOKEN).getValue(), token));
}
private String buildKey(String type, String id) {
@@ -173,16 +162,16 @@ public class PigxRedisOAuth2AuthorizationService implements OAuth2AuthorizationS
// 扩展记录 access-token 、username 的关系 1::token::username::admin::xxx
String tokenUsernameKey = String.format("%s::%s::%s::*", AUTHORIZATION,
SecurityConstants.DETAILS_USERNAME, authenticationName);
Set<String> keys = redisTemplate.keys(tokenUsernameKey);
Set<String> keys = RedisUtils.keys(tokenUsernameKey);
if (CollUtil.isEmpty(keys)) {
return;
}
List<Object> tokenList = redisTemplate.opsForValue().multiGet(keys);
List<String> tokenList = RedisUtils.multiGet(keys.stream().toList());
for (Object token : tokenList) {
for (String token : tokenList) {
// 根据token 查询存储的 OAuth2Authorization
OAuth2Authorization authorization = this.findByToken((String) token, OAuth2TokenType.ACCESS_TOKEN);
OAuth2Authorization authorization = this.findByToken(token, OAuth2TokenType.ACCESS_TOKEN);
// 根据 OAuth2Authorization 删除相关令牌
this.remove(authorization);
}
@@ -5,7 +5,10 @@ import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.experimental.FieldNameConstants;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 短信发送
@@ -1,9 +1,9 @@
package com.pig4cloud.pigx.admin.api.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import java.time.LocalDateTime;
/**
@@ -19,42 +19,43 @@
package com.pig4cloud.pigx.admin.api.dto;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.pig4cloud.pigx.admin.api.vo.UserVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* Spring Security 用户信息实体类,继承自UserVO并实现Serializable接口
*
* @author lengleng
* @date 2017/11/11
* @date 2025/06/30
*/
@Data
@Schema(description = "用户信息")
public class UserInfo implements Serializable {
@EqualsAndHashCode(callSuper = true)
public class UserInfo extends UserVO implements Serializable {
/**
* 用户基本信息
* 密码
*/
@Schema(description = "用户基本信息")
private SysUser sysUser;
@JsonIgnore(value = false)
private String password;
/**
* 随机盐
*/
@JsonIgnore(value = false)
private String salt;
/**
* 权限标识集合
*/
@Schema(description = "权限标识集合")
private String[] permissions;
/**
* 角色集合
*/
@Schema(description = "角色标识集合")
private Long[] roles;
/**
* 部门ID
*/
@Schema(description = "用户所属部门id")
private Long deptId;
private List<String> permissions = new ArrayList<>();
}
@@ -23,11 +23,11 @@ import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.pig4cloud.pigx.common.core.util.TenantTable;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
/**
@@ -23,10 +23,10 @@ import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.pig4cloud.pigx.common.core.util.TenantTable;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.NotBlank;
import java.time.LocalDateTime;
/**
@@ -21,11 +21,11 @@ import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.pig4cloud.pigx.common.core.util.TenantTable;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
/**
@@ -23,11 +23,11 @@ import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.pig4cloud.pigx.common.core.util.TenantTable;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
/**
@@ -2,10 +2,11 @@ package com.pig4cloud.pigx.admin.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.pig4cloud.pigx.common.core.util.TenantTable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.pig4cloud.pigx.common.core.util.TenantTable;
import java.time.LocalDateTime;
/**
@@ -2,10 +2,10 @@ package com.pig4cloud.pigx.admin.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.pig4cloud.pigx.common.core.util.TenantTable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.pig4cloud.pigx.common.core.util.TenantTable;
import lombok.experimental.FieldNameConstants;
import java.time.LocalDateTime;
@@ -3,9 +3,9 @@ package com.pig4cloud.pigx.admin.api.vo;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.pig4cloud.pigx.common.excel.annotation.ExcelLine;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import java.io.Serializable;
/**
@@ -3,9 +3,9 @@ package com.pig4cloud.pigx.admin.api.vo;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.pig4cloud.pigx.common.excel.annotation.ExcelLine;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import java.io.Serializable;
/**
@@ -3,11 +3,17 @@ package com.pig4cloud.pigx.admin.api.vo;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.pig4cloud.pigx.common.excel.annotation.ExcelLine;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* 钉钉用户Excel导入导出VO
*
* @author lengleng
* @date 2025/06/30
*/
@Data
public class DingUserExcelVo implements Serializable {
@@ -4,10 +4,10 @@ import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.pig4cloud.pigx.common.excel.annotation.ExcelLine;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@@ -4,9 +4,9 @@ import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.pig4cloud.pigx.common.excel.annotation.ExcelLine;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import java.io.Serializable;
import java.time.LocalDateTime;
@@ -4,6 +4,7 @@ import cn.hutool.core.util.StrUtil;
import com.pig4cloud.pigx.admin.service.SysOauthClientDetailsService;
import com.pig4cloud.pigx.admin.service.SysTenantService;
import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import com.pig4cloud.pigx.common.data.tenant.TenantBroker;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -12,7 +13,6 @@ import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.scheduling.annotation.Async;
@@ -37,8 +37,6 @@ public class ClientDetailsInitRunner implements InitializingBean {
private final SysTenantService tenantService;
private final StringRedisTemplate redisTemplate;
/**
* WebServerInitializedEvent 使用 TransactionalEventListener 时启动时无法获取到事件
*/
@@ -65,7 +63,7 @@ public class ClientDetailsInitRunner implements InitializingBean {
// 3. 拼接key 1:client_config_flag:clinetId
String key = String.format("%s:%s:%s", tenantId, CacheConstants.CLIENT_FLAG, client.getClientId());
// 4. hashkey clientId 保存客户端信息
redisTemplate.opsForValue().set(key, client.getAdditionalInformation());
RedisUtils.set(key, client.getAdditionalInformation());
});
});
});
@@ -21,6 +21,7 @@ import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.pig4cloud.pigx.admin.service.SysRouteConfService;
import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import com.pig4cloud.pigx.common.gateway.support.DynamicRouteInitEvent;
import com.pig4cloud.pigx.common.gateway.vo.RouteDefinitionVo;
import lombok.RequiredArgsConstructor;
@@ -33,11 +34,9 @@ import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.event.TransactionalEventListener;
@@ -45,10 +44,10 @@ import java.net.URI;
import java.util.Map;
/**
* 动态路由初始化运行器:容器启动后保存配置文件里面的路由信息到Redis
*
* @author lengleng
* @date 2018/10/31
* <p>
* 容器启动后保存配置文件里面的路由信息到Redis
*/
@Slf4j
@Configuration
@@ -56,8 +55,6 @@ import java.util.Map;
@ConditionalOnDiscoveryEnabled
public class DynamicRouteInitRunner implements InitializingBean {
private final RedisTemplate<String, String> redisTemplate;
private final SysRouteConfService routeConfService;
private final RedisMessageListenerContainer listenerContainer;
@@ -76,7 +73,7 @@ public class DynamicRouteInitRunner implements InitializingBean {
@Order
@TransactionalEventListener({DynamicRouteInitEvent.class})
public void initRoute() {
redisTemplate.delete(CacheConstants.ROUTE_KEY);
RedisUtils.delete(CacheConstants.ROUTE_KEY);
log.info("开始初始化网关路由");
routeConfService.list().forEach(route -> {
@@ -93,13 +90,14 @@ public class DynamicRouteInitRunner implements InitializingBean {
vo.setMetadata(JSONUtil.toBean(route.getMetadata(), Map.class));
log.info("加载路由ID:{},{}", route.getRouteId(), vo);
redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(RouteDefinitionVo.class));
HashOperations<String, String, RouteDefinitionVo> stringStringValueOperations = redisTemplate.opsForHash();
stringStringValueOperations.put(CacheConstants.ROUTE_KEY, route.getRouteId(), vo);
RedisUtils.hset(CacheConstants.ROUTE_KEY, route.getRouteId(), vo);
});
// 通知网关重置路由
redisTemplate.convertAndSend(CacheConstants.ROUTE_JVM_RELOAD_TOPIC, "路由信息,网关缓存更新");
RedisUtils.execute((RedisCallback<Void>) connection -> {
connection.publish(CacheConstants.ROUTE_JVM_RELOAD_TOPIC.getBytes(), "路由信息,网关缓存更新".getBytes());
return null;
});
log.debug("初始化网关路由结束 ");
}
@@ -31,8 +31,9 @@ public class ConnectController {
private final SysDeptService deptService;
/**
* 同步钉钉用户
* @return
* 同步钉钉用户信息
*
* @return 操作结果
*/
@PostMapping("/sync/ding/user")
@HasPermission("sys_connect_sync")
@@ -44,8 +45,10 @@ public class ConnectController {
}
/**
* 同步钉钉部门
* @return
* 同步钉钉部门信息
*
* @return 同步操作结果
* @see R
*/
@PostMapping("/sync/ding/dept")
@HasPermission("sys_connect_sync")
@@ -54,8 +57,9 @@ public class ConnectController {
}
/**
* 同步企微用户
* @return
* 同步企业微信用户信息
*
* @return 同步操作结果
*/
@PostMapping("/sync/cp/user")
@HasPermission("sys_connect_sync")
@@ -64,8 +68,9 @@ public class ConnectController {
}
/**
* 同步企微部门
* @return
* 同步企业微信部门信息
*
* @return 包含同步结果的响应对象
*/
@PostMapping("/sync/cp/dept")
@HasPermission("sys_connect_sync")
@@ -17,19 +17,9 @@
package com.pig4cloud.pigx.admin.controller;
import java.util.List;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -40,14 +30,15 @@ import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import com.pig4cloud.pigx.common.security.annotation.HasPermission;
import com.pig4cloud.pigx.common.security.annotation.Inner;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 公共参数
@@ -10,6 +10,7 @@ import com.pig4cloud.pigx.admin.api.entity.SysSensitiveWordEntity;
import com.pig4cloud.pigx.admin.service.SysSensitiveWordService;
import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import com.pig4cloud.pigx.common.security.annotation.HasPermission;
@@ -19,7 +20,7 @@ import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
@@ -40,8 +41,6 @@ public class SysSensitiveWordController {
private final SysSensitiveWordService sysSensitiveWordService;
private final RedisTemplate<String, Object> redisTemplate;
/**
* 分页查询
*
@@ -107,7 +106,10 @@ public class SysSensitiveWordController {
@HasPermission("admin_sysSensitiveWord_edit")
public R updateById(@RequestBody SysSensitiveWordEntity sysSensitiveWord) {
sysSensitiveWordService.updateById(sysSensitiveWord);
redisTemplate.convertAndSend(CacheConstants.SENSITIVE_REDIS_RELOAD_TOPIC, "刷新敏感词缓存");
RedisUtils.execute((RedisCallback<Void>) connection -> {
connection.publish(CacheConstants.SENSITIVE_REDIS_RELOAD_TOPIC.getBytes(), "刷新敏感词缓存".getBytes());
return null;
});
return R.ok();
}
@@ -137,7 +139,10 @@ public class SysSensitiveWordController {
@HasPermission("admin_sysSensitiveWord_del")
public R removeById(@RequestBody Long[] ids) {
sysSensitiveWordService.removeBatchByIds(CollUtil.toList(ids));
redisTemplate.convertAndSend(CacheConstants.SENSITIVE_REDIS_RELOAD_TOPIC, "刷新敏感词缓存");
RedisUtils.execute((RedisCallback<Void>) connection -> {
connection.publish(CacheConstants.SENSITIVE_REDIS_RELOAD_TOPIC.getBytes(), "刷新敏感词缓存".getBytes());
return null;
});
return R.ok();
}
@@ -165,7 +170,10 @@ public class SysSensitiveWordController {
@GetMapping("/refresh")
@HasPermission("admin_sysSensitiveWord_del")
public R refresh() {
redisTemplate.convertAndSend(CacheConstants.SENSITIVE_REDIS_RELOAD_TOPIC, "刷新敏感词缓存");
RedisUtils.execute((RedisCallback<Void>) connection -> {
connection.publish(CacheConstants.SENSITIVE_REDIS_RELOAD_TOPIC.getBytes(), "刷新敏感词缓存".getBytes());
return null;
});
return R.ok();
}
}
@@ -1,13 +1,13 @@
package com.pig4cloud.pigx.admin.controller;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.connection.RedisServerCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -22,18 +22,16 @@ import java.util.*;
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class SysSystemInfoController {
private final RedisTemplate<String, String> redisTemplate;
/**
* 缓存监控
* @return R<Object>
*/
@GetMapping("/cache")
public R cache() {
Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) RedisServerCommands::info);
Properties commandStats = (Properties) redisTemplate
.execute((RedisCallback<Object>) connection -> connection.serverCommands().info("commandstats"));
Object dbSize = redisTemplate.execute((RedisCallback<Object>) RedisServerCommands::dbSize);
Properties info = RedisUtils.execute((RedisCallback<Properties>) RedisServerCommands::info);
Properties commandStats = RedisUtils.execute((RedisCallback<Properties>)
connection -> connection.serverCommands().info("commandstats"));
Object dbSize = RedisUtils.execute((RedisCallback<Object>) RedisServerCommands::dbSize);
if (commandStats == null) {
return R.failed("获取异常");
@@ -28,10 +28,7 @@ import com.pig4cloud.pigx.admin.api.entity.SysUser;
import com.pig4cloud.pigx.admin.api.vo.UserExcelVO;
import com.pig4cloud.pigx.admin.service.SysUserService;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.core.exception.ErrorCodes;
import com.pig4cloud.pigx.common.core.util.MsgUtils;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.data.tenant.TenantBroker;
import com.pig4cloud.pigx.common.excel.annotation.RequestExcel;
import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
@@ -73,12 +70,9 @@ public class SysUserController {
@Inner
@GetMapping("/info/{username}")
public R info(@PathVariable String username) {
SysUser user = TenantBroker.noneAs(() -> userService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getUsername, username), false));
if (user == null) {
return R.failed(MsgUtils.getMessage(ErrorCodes.SYS_USER_USERINFO_EMPTY, username));
}
return TenantBroker.applyAs(user.getTenantId(), tenantId -> R.ok(userService.findUserInfo(user)));
UserDTO userDTO = new UserDTO();
userDTO.setUsername(username);
return userService.getUserInfo(userDTO);
}
/**
@@ -89,18 +83,14 @@ public class SysUserController {
@GetMapping(value = {"/info"})
public R info() {
String username = SecurityUtils.getUser().getUsername();
SysUser user = TenantBroker.noneAs(() -> userService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getUsername, username), false));
if (user == null) {
return R.failed(MsgUtils.getMessage(ErrorCodes.SYS_USER_QUERY_ERROR));
UserDTO userDTO = new UserDTO();
userDTO.setUsername(username);
// 获取用户信息,不返回数据库密码字段
R<UserInfo> userInfoR = userService.getUserInfo(userDTO);
if (userInfoR.getData() != null) {
userInfoR.getData().setPassword(null);
}
return TenantBroker.applyAs(user.getTenantId(), tenantId -> {
// UserInfo 是复用对象,不能通过设置 @jsonIgnore 来忽略密码字段
UserInfo userInfo = userService.findUserInfo(user);
userInfo.getSysUser().setPassword(null);
return R.ok(userInfo);
});
return userInfoR;
}
/**
@@ -18,13 +18,13 @@
package com.pig4cloud.pigx.admin.handler;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pig4cloud.pigx.admin.api.dto.UserDTO;
import com.pig4cloud.pigx.admin.api.dto.UserInfo;
import com.pig4cloud.pigx.admin.api.entity.SysSocialDetails;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
import com.pig4cloud.pigx.admin.mapper.SysSocialDetailsMapper;
import com.pig4cloud.pigx.admin.service.SysUserService;
import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum;
import com.pig4cloud.pigx.common.core.util.R;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
@@ -65,19 +65,24 @@ public class CasLoginHandler extends AbstractLoginHandler {
}
/**
* username 获取用户信息
* @param username
* @return
* 根据用户名获取用户信息
*
* @param username 用户名
* @return 用户信息对象,如果用户不存在则返回null
*/
@Override
public UserInfo info(String username) {
SysUser user = sysUserService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getUsername, username));
UserDTO userDTO = new UserDTO();
userDTO.setUsername(username);
if (user == null) {
R<UserInfo> userInfoR = sysUserService.getUserInfo(userDTO);
if (userInfoR.getData() == null) {
log.info("CAS 不存在用户:{}", username);
return null;
}
return sysUserService.findUserInfo(user);
return userInfoR.getData();
}
}
@@ -21,13 +21,14 @@ import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pig4cloud.pigx.admin.api.dto.UserDTO;
import com.pig4cloud.pigx.admin.api.dto.UserInfo;
import com.pig4cloud.pigx.admin.api.entity.SysSocialDetails;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
import com.pig4cloud.pigx.admin.mapper.SysSocialDetailsMapper;
import com.pig4cloud.pigx.admin.service.SysUserService;
import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum;
import com.pig4cloud.pigx.common.core.util.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@@ -35,7 +36,7 @@ import org.springframework.stereotype.Component;
/**
* @author lengleng
* @date 2023-10-14
*
* <p>
* 钉钉登录
*/
@Slf4j
@@ -43,71 +44,78 @@ import org.springframework.stereotype.Component;
@AllArgsConstructor
public class DingTalkLoginHandler extends AbstractLoginHandler {
private final SysUserService sysUserService;
private final SysUserService sysUserService;
private final SysSocialDetailsMapper sysSocialDetailsMapper;
private final SysSocialDetailsMapper sysSocialDetailsMapper;
/**
* QQ登录传入code
* <p>
* 通过code 调用qq 获取唯一标识
* @param code
* @return
*/
@Override
public String identify(String code) {
SysSocialDetails condition = new SysSocialDetails();
condition.setType(LoginTypeEnum.DINGTALK.getType());
SysSocialDetails socialDetails = sysSocialDetailsMapper.selectOne(new QueryWrapper<>(condition));
/**
* QQ登录传入code
* <p>
* 通过code 调用qq 获取唯一标识
*
* @param code
* @return
*/
@Override
public String identify(String code) {
SysSocialDetails condition = new SysSocialDetails();
condition.setType(LoginTypeEnum.DINGTALK.getType());
SysSocialDetails socialDetails = sysSocialDetailsMapper.selectOne(new QueryWrapper<>(condition));
String getAccessTokenUrl = "https://api.dingtalk.com/v1.0/oauth2/userAccessToken";
String accessTokenResult = HttpUtil.post(getAccessTokenUrl,
JSONUtil.createObj()
.set("clientId", socialDetails.getAppId())
.set("clientSecret", socialDetails.getAppSecret())
.set("grantType", "authorization_code")
.set("code", code)
.toString());
log.debug("获取钉钉Token响应报文:{}", accessTokenResult);
String accessToken = JSONUtil.parseObj(accessTokenResult).getStr("accessToken");
String getUserIdUrl = "https://api.dingtalk.com/v1.0/contact/users/me";
String getAccessTokenUrl = "https://api.dingtalk.com/v1.0/oauth2/userAccessToken";
String accessTokenResult = HttpUtil.post(getAccessTokenUrl,
JSONUtil.createObj()
.set("clientId", socialDetails.getAppId())
.set("clientSecret", socialDetails.getAppSecret())
.set("grantType", "authorization_code")
.set("code", code)
.toString());
log.debug("获取钉钉Token响应报文:{}", accessTokenResult);
String accessToken = JSONUtil.parseObj(accessTokenResult).getStr("accessToken");
String getUserIdUrl = "https://api.dingtalk.com/v1.0/contact/users/me";
String userResult = HttpRequest.get(getUserIdUrl)
.header("x-acs-dingtalk-access-token", accessToken)
.execute()
.body();
log.debug("获取钉钉UserId响应报文:{}", userResult);
// 企微唯一标识
return JSONUtil.parseObj(userResult).getStr("openId");
}
String userResult = HttpRequest.get(getUserIdUrl)
.header("x-acs-dingtalk-access-token", accessToken)
.execute()
.body();
log.debug("获取钉钉UserId响应报文:{}", userResult);
// 企微唯一标识
return JSONUtil.parseObj(userResult).getStr("openId");
}
/**
* openId 获取用户信息
* @param openId
* @return
*/
@Override
public UserInfo info(String openId) {
SysUser user = sysUserService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getWxDingUserid, openId));
/**
* 根据openId获取用户信息
*
* @param openId 用户openId
* @return 用户信息,不存在时返回null
*/
@Override
public UserInfo info(String openId) {
UserDTO userDTO = new UserDTO();
userDTO.setWxDingUserid(openId);
if (user == null) {
log.info("钉钉未绑定:{}", openId);
return null;
}
return sysUserService.findUserInfo(user);
}
R<UserInfo> userInfoR = sysUserService.getUserInfo(userDTO);
/**
* 绑定逻辑
* @param user 用户实体
* @param identify 渠道返回唯一标识
* @return
*/
@Override
public Boolean bind(SysUser user, String identify) {
user.setWxDingUserid(identify);
sysUserService.updateById(user);
return true;
}
if (userInfoR.getData() == null) {
log.info("钉钉不存在用户:{}", openId);
return null;
}
return userInfoR.getData();
}
/**
* 绑定逻辑
*
* @param user 用户实体
* @param identify 渠道返回唯一标识
* @return
*/
@Override
public Boolean bind(SysUser user, String identify) {
user.setWxDingUserid(identify);
sysUserService.updateById(user);
return true;
}
}
@@ -22,7 +22,7 @@ import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pig4cloud.pigx.admin.api.dto.UserDTO;
import com.pig4cloud.pigx.admin.api.dto.UserInfo;
import com.pig4cloud.pigx.admin.api.entity.SysSocialDetails;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
@@ -30,6 +30,7 @@ import com.pig4cloud.pigx.admin.mapper.SysSocialDetailsMapper;
import com.pig4cloud.pigx.admin.service.SysUserService;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum;
import com.pig4cloud.pigx.common.core.util.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@@ -80,20 +81,25 @@ public class GiteeLoginHandler extends AbstractLoginHandler {
}
/**
* identify 获取用户信息
* @param identify identify
* @return
* 根据标识获取用户信息
*
* @param identify 用户标识
* @return 用户信息,未找到时返回null
*/
@Override
public UserInfo info(String identify) {
SysUser user = sysUserService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getGiteeLogin, identify));
UserDTO userDTO = new UserDTO();
userDTO.setGiteeLogin(identify);
if (user == null) {
log.info("码云未绑定:{}", identify);
R<UserInfo> userInfoR = sysUserService.getUserInfo(userDTO);
if (userInfoR.getData() == null) {
log.info("微信 不存在用户:{}", identify);
return null;
}
return sysUserService.findUserInfo(user);
return userInfoR.getData();
}
/**
@@ -21,7 +21,7 @@ import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pig4cloud.pigx.admin.api.dto.UserDTO;
import com.pig4cloud.pigx.admin.api.dto.UserInfo;
import com.pig4cloud.pigx.admin.api.entity.SysSocialDetails;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
@@ -30,6 +30,7 @@ import com.pig4cloud.pigx.admin.service.SysUserService;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum;
import com.pig4cloud.pigx.common.core.exception.CheckedException;
import com.pig4cloud.pigx.common.core.util.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@@ -79,20 +80,24 @@ public class MiniAppLoginHandler extends AbstractLoginHandler {
}
/**
* openId 获取用户信息
* 根据openId获取用户信息
*
* @param openId
* @return
* @param openId 用户openId
* @return 用户信息对象,未找到时返回null
*/
@Override
public UserInfo info(String openId) {
SysUser user = sysUserService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getMiniOpenid, openId));
UserDTO userDTO = new UserDTO();
userDTO.setMiniOpenid(openId);
if (user == null) {
log.info("微信小程序未绑定:{}", openId);
R<UserInfo> userInfoR = sysUserService.getUserInfo(userDTO);
if (userInfoR.getData() == null) {
log.info("小程序不存在用户:{}", openId);
return null;
}
return sysUserService.findUserInfo(user);
return userInfoR.getData();
}
/**
@@ -21,7 +21,7 @@ import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pig4cloud.pigx.admin.api.dto.UserDTO;
import com.pig4cloud.pigx.admin.api.dto.UserInfo;
import com.pig4cloud.pigx.admin.api.entity.SysSocialDetails;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
@@ -29,6 +29,7 @@ import com.pig4cloud.pigx.admin.mapper.SysSocialDetailsMapper;
import com.pig4cloud.pigx.admin.service.SysUserService;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum;
import com.pig4cloud.pigx.common.core.util.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@@ -47,75 +48,81 @@ import java.util.Map;
@AllArgsConstructor
public class OscChinaLoginHandler extends AbstractLoginHandler {
private final SysSocialDetailsMapper sysSocialDetailsMapper;
private final SysSocialDetailsMapper sysSocialDetailsMapper;
private final SysUserService sysUserService;
private final SysUserService sysUserService;
/**
* 开源中国传入code
* <p>
* 通过code 调用qq 获取唯一标识
* @param code
* @return
*/
@Override
public String identify(String code) {
SysSocialDetails condition = new SysSocialDetails();
condition.setType(LoginTypeEnum.OSC.getType());
SysSocialDetails socialDetails = sysSocialDetailsMapper.selectOne(new QueryWrapper<>(condition));
/**
* 开源中国传入code
* <p>
* 通过code 调用qq 获取唯一标识
*
* @param code
* @return
*/
@Override
public String identify(String code) {
SysSocialDetails condition = new SysSocialDetails();
condition.setType(LoginTypeEnum.OSC.getType());
SysSocialDetails socialDetails = sysSocialDetailsMapper.selectOne(new QueryWrapper<>(condition));
Map<String, Object> params = new HashMap<>(8);
Map<String, Object> params = new HashMap<>(8);
params.put("client_id", socialDetails.getAppId());
params.put("client_secret", socialDetails.getAppSecret());
params.put("grant_type", "authorization_code");
params.put("redirect_uri", socialDetails.getRedirectUrl());
params.put("code", code);
params.put("dataType", "json");
params.put("client_id", socialDetails.getAppId());
params.put("client_secret", socialDetails.getAppSecret());
params.put("grant_type", "authorization_code");
params.put("redirect_uri", socialDetails.getRedirectUrl());
params.put("code", code);
params.put("dataType", "json");
String result = HttpUtil.post(SecurityConstants.OSC_AUTHORIZATION_CODE_URL, params);
log.debug("开源中国响应报文:{}", result);
String result = HttpUtil.post(SecurityConstants.OSC_AUTHORIZATION_CODE_URL, params);
log.debug("开源中国响应报文:{}", result);
String accessToken = JSONUtil.parseObj(result).getStr("access_token");
String accessToken = JSONUtil.parseObj(result).getStr("access_token");
String url = String.format(SecurityConstants.OSC_USER_INFO_URL, accessToken);
String resp = HttpUtil.get(url);
log.debug("开源中国获取个人信息返回报文{}", resp);
String url = String.format(SecurityConstants.OSC_USER_INFO_URL, accessToken);
String resp = HttpUtil.get(url);
log.debug("开源中国获取个人信息返回报文{}", resp);
JSONObject userInfo = JSONUtil.parseObj(resp);
// 开源中国唯一标识
String id = userInfo.getStr("id");
return id;
}
JSONObject userInfo = JSONUtil.parseObj(resp);
// 开源中国唯一标识
String id = userInfo.getStr("id");
return id;
}
/**
* identify 获取用户信息
* @param identify 开源中国表示
* @return
*/
@Override
public UserInfo info(String identify) {
/**
* 根据开源中国标识获取用户信息
*
* @param identify 开源中国用户标识
* @return 用户信息对象,未找到时返回null
*/
@Override
public UserInfo info(String identify) {
UserDTO userDTO = new UserDTO();
userDTO.setOscId(identify);
SysUser user = sysUserService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getOscId, identify));
R<UserInfo> userInfoR = sysUserService.getUserInfo(userDTO);
if (user == null) {
log.info("开源中国未绑定:{}", identify);
return null;
}
return sysUserService.findUserInfo(user);
}
if (userInfoR.getData() == null) {
log.info("开源中国 不存在用户:{}", identify);
return null;
}
/**
* 绑定逻辑
* @param user 用户实体
* @param identify 渠道返回唯一标识
* @return
*/
@Override
public Boolean bind(SysUser user, String identify) {
user.setOscId(identify);
sysUserService.updateById(user);
return true;
}
return userInfoR.getData();
}
/**
* 绑定逻辑
*
* @param user 用户实体
* @param identify 渠道返回唯一标识
* @return
*/
@Override
public Boolean bind(SysUser user, String identify) {
user.setOscId(identify);
sysUserService.updateById(user);
return true;
}
}
@@ -17,10 +17,11 @@
package com.pig4cloud.pigx.admin.handler;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pig4cloud.pigx.admin.api.dto.UserDTO;
import com.pig4cloud.pigx.admin.api.dto.UserInfo;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
import com.pig4cloud.pigx.admin.service.SysUserService;
import com.pig4cloud.pigx.common.core.util.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@@ -47,19 +48,24 @@ public class SmsLoginHandler extends AbstractLoginHandler {
}
/**
* 通过mobile 获取用户信息
* @param identify
* @return
* 通过手机号获取用户信息
*
* @param identify 手机号标识
* @return 用户信息,未找到时返回null
*/
@Override
public UserInfo info(String identify) {
SysUser user = sysUserService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getPhone, identify));
UserDTO userDTO = new UserDTO();
userDTO.setPhone(identify);
if (user == null) {
log.info("手机号未注册:{}", identify);
R<UserInfo> userInfoR = sysUserService.getUserInfo(userDTO);
if (userInfoR.getData() == null) {
log.info("手机号 不存在用户:{}", identify);
return null;
}
return sysUserService.findUserInfo(user);
return userInfoR.getData();
}
/**
@@ -1,107 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.admin.handler;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pig4cloud.pigx.admin.api.dto.UserInfo;
import com.pig4cloud.pigx.admin.api.entity.SysSocialDetails;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
import com.pig4cloud.pigx.admin.mapper.SysSocialDetailsMapper;
import com.pig4cloud.pigx.admin.service.SysUserService;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @author lengleng
* @date 2018/11/18
*/
@Slf4j
@Component("QQ")
@AllArgsConstructor
public class TencentLoginHandler extends AbstractLoginHandler {
private final SysUserService sysUserService;
private final SysSocialDetailsMapper sysSocialDetailsMapper;
/**
* QQ登录传入code
* <p>
* 通过code 调用qq 获取唯一标识
* @param code
* @return
*/
@Override
public String identify(String code) {
SysSocialDetails condition = new SysSocialDetails();
condition.setType(LoginTypeEnum.QQ.getType());
SysSocialDetails socialDetails = sysSocialDetailsMapper.selectOne(new QueryWrapper<>(condition));
String url = String.format(SecurityConstants.QQ_AUTHORIZATION_CODE_URL, socialDetails.getAppId(),
socialDetails.getAppSecret(), code);
String result = HttpUtil.get(url);
log.debug("QQ响应报文:{}", result);
String accessToken = JSONUtil.parseObj(result).getStr("access_token");
String userUrl = String.format(SecurityConstants.QQ_USER_INFO_URL, accessToken);
String resp = HttpUtil.get(userUrl);
log.debug("QQ获取个人信息返回报文{}", resp);
JSONObject userInfo = JSONUtil.parseObj(resp);
// QQ唯一标识
String openid = userInfo.getStr("openid");
return openid;
}
/**
* openId 获取用户信息
* @param openId
* @return
*/
@Override
public UserInfo info(String openId) {
SysUser user = sysUserService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getQqOpenid, openId));
if (user == null) {
log.info("QQ未绑定:{}", openId);
return null;
}
return sysUserService.findUserInfo(user);
}
/**
* 绑定逻辑
* @param user 用户实体
* @param identify 渠道返回唯一标识
* @return
*/
@Override
public Boolean bind(SysUser user, String identify) {
user.setQqOpenid(identify);
sysUserService.updateById(user);
return true;
}
}
@@ -20,14 +20,14 @@ package com.pig4cloud.pigx.admin.handler;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pig4cloud.pigx.admin.api.dto.UserDTO;
import com.pig4cloud.pigx.admin.api.dto.UserInfo;
import com.pig4cloud.pigx.admin.api.entity.SysSocialDetails;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
import com.pig4cloud.pigx.admin.mapper.SysSocialDetailsMapper;
import com.pig4cloud.pigx.admin.service.SysUserService;
import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum;
import lombok.AllArgsConstructor;
import com.pig4cloud.pigx.common.core.util.R;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@@ -75,20 +75,24 @@ public class WeChatCPLoginHandler extends AbstractLoginHandler {
}
/**
* openId 获取用户信息
* 根据openId获取用户信息
*
* @param openId
* @return
* @param openId 用户openId
* @return 用户信息对象,未找到时返回null
*/
@Override
public UserInfo info(String openId) {
SysUser user = sysUserService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getWxCpUserid, openId));
UserDTO userDTO = new UserDTO();
userDTO.setWxCpUserid(openId);
if (user == null) {
log.info("企业微信未绑定:{}", openId);
R<UserInfo> userInfoR = sysUserService.getUserInfo(userDTO);
if (userInfoR.getData() == null) {
log.info("企业微信 不存在用户:{}", openId);
return null;
}
return sysUserService.findUserInfo(user);
return userInfoR.getData();
}
/**
@@ -20,7 +20,7 @@ package com.pig4cloud.pigx.admin.handler;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pig4cloud.pigx.admin.api.dto.UserDTO;
import com.pig4cloud.pigx.admin.api.dto.UserInfo;
import com.pig4cloud.pigx.admin.api.entity.SysSocialDetails;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
@@ -28,6 +28,7 @@ import com.pig4cloud.pigx.admin.mapper.SysSocialDetailsMapper;
import com.pig4cloud.pigx.admin.service.SysUserService;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum;
import com.pig4cloud.pigx.common.core.util.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@@ -68,19 +69,24 @@ public class WeChatLoginHandler extends AbstractLoginHandler {
}
/**
* openId 获取用户信息
* @param openId
* @return
* 根据微信openId获取用户信息
*
* @param openId 微信openId
* @return 用户信息,未找到时返回null
*/
@Override
public UserInfo info(String openId) {
SysUser user = sysUserService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getWxOpenid, openId));
UserDTO userDTO = new UserDTO();
userDTO.setWxOpenid(openId);
if (user == null) {
log.info("微信未绑定:{}", openId);
R<UserInfo> userInfoR = sysUserService.getUserInfo(userDTO);
if (userInfoR.getData() == null) {
log.info("微信 不存在用户:{}", openId);
return null;
}
return sysUserService.findUserInfo(user);
return userInfoR.getData();
}
/**
@@ -1,7 +1,7 @@
package com.pig4cloud.pigx.admin.mapper;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import com.pig4cloud.pigx.admin.api.entity.SysAreaEntity;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
@@ -1,7 +1,7 @@
package com.pig4cloud.pigx.admin.mapper;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import com.pig4cloud.pigx.admin.api.entity.SysSensitiveWordEntity;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
@@ -19,6 +19,7 @@
package com.pig4cloud.pigx.admin.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.admin.api.dto.UserDTO;
@@ -32,45 +33,49 @@ import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* 用户表 Mapper 接口
* </p>
*
* @author lengleng
* @since 2017-10-29
* @date 2025/06/30
*/
@Mapper
public interface SysUserMapper extends PigxBaseMapper<SysUser> {
/**
* 通过用户名查询用户信息(含有角色信息)
* @param username 用户名
* @return userVo
*/
UserVO getUserVoByUsername(String username);
/**
* 通过用户DTO查询用户信息(包含角色信息)
*
* @param userDTO 用户查询DTO
* @return 包含角色信息的用户VO
*/
@InterceptorIgnore(tenantLine = "true")
UserVO getUserVo(@Param("query") UserDTO userDTO);
/**
* 分页查询用户信息(含角色)
* @param page 分页
* @param userDTO 查询参数
* @param dataScope
* @return list
*/
IPage<UserVO> getUserVosPage(Page page, @Param("query") UserDTO userDTO, DataScope dataScope);
/**
* 分页查询用户信息(含角色)
*
* @param page 分页对象
* @param userDTO 用户查询参数
* @param dataScope 数据权限范围
* @return 分页用户信息列表
*/
IPage<UserVO> getUserVosPage(Page page, @Param("query") UserDTO userDTO, DataScope dataScope);
/**
* 通过ID查询用户信息
* @param id 用户ID
* @return userVo
*/
UserVO getUserVoById(Long id);
/**
* 通过ID查询用户信息
*
* @param id 用户ID
* @return 用户信息VO对象
*/
UserVO getUserVoById(Long id);
/**
* 查询用户列表
* @param userDTO 查询条件
* @param dataScope 数据权限声明
* @return
*/
List<UserVO> selectVoListByScope(@Param("query") UserDTO userDTO, @Param("ids") Long[] ids, DataScope dataScope);
/**
* 根据数据权限查询用户列表
*
* @param userDTO 查询条件
* @param ids 用户ID数组
* @param dataScope 数据权限声明
* @return 用户VO列表
*/
List<UserVO> selectVoListByScope(@Param("query") UserDTO userDTO, @Param("ids") Long[] ids, DataScope dataScope);
}
@@ -42,10 +42,10 @@ public interface SysUserService extends IService<SysUser> {
/**
* 查询用户信息
*
* @param sysUser 用户
* @return userInfo
* @param userDTO 用户数据传输对象
* @return 用户信息对象
*/
UserInfo findUserInfo(SysUser sysUser);
R<UserInfo> getUserInfo(UserDTO userDTO);
/**
* 分页查询用户信息(含有角色信息)
@@ -42,6 +42,7 @@ import com.pig4cloud.pigx.common.core.exception.CheckedException;
import com.pig4cloud.pigx.common.core.exception.ErrorCodes;
import com.pig4cloud.pigx.common.core.util.MsgUtils;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder;
import com.pig4cloud.pigx.common.file.core.FileTemplate;
import com.pig4cloud.pigx.common.log.util.JacksonSensitiveFieldUtil;
@@ -76,7 +77,6 @@ import org.dromara.sms4j.unisms.config.UniConfig;
import org.dromara.sms4j.yunpian.config.YunpianConfig;
import org.dromara.sms4j.zhutong.config.ZhutongConfig;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -85,7 +85,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* 站内信息
@@ -109,8 +109,6 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
private final SysMessageRelationMapper relationMapper;
private final StringRedisTemplate redisTemplate;
private final SysUserMapper userMapper;
private final SysFileMapper fileMapper;
@@ -259,7 +257,7 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
return R.ok(Boolean.FALSE, MsgUtils.getMessage(ErrorCodes.SYS_APP_PHONE_UNREGISTERED, mobile));
}
String codeObj = redisTemplate.opsForValue().get(CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.SMS.getType() + StringPool.AT + mobile);
String codeObj = RedisUtils.get(CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.SMS.getType() + StringPool.AT + mobile);
if (StrUtil.isNotBlank(codeObj)) {
log.info("手机号验证码未过期:{},{}", mobile, codeObj);
@@ -268,7 +266,7 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
String code = RandomUtil.randomNumbers(Integer.parseInt(SecurityConstants.CODE_SIZE));
log.info("手机号生成验证码成功:{},{}", mobile, code);
redisTemplate.opsForValue().set(CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.SMS.getType() + StringPool.AT + mobile, code, SecurityConstants.CODE_TIME, TimeUnit.SECONDS);
RedisUtils.set(CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.SMS.getType() + StringPool.AT + mobile, code, SecurityConstants.CODE_TIME);
// 发送
return this.sendSms(MessageSmsDTO.builder().mobile(mobile).biz(SmsBizCodeEnum.SMS_NORMAL_CODE.getCode()).param(code).build());
@@ -9,8 +9,9 @@ import com.pig4cloud.pigx.admin.api.entity.SysSensitiveWordEntity;
import com.pig4cloud.pigx.admin.mapper.SysSensitiveWordMapper;
import com.pig4cloud.pigx.admin.service.SysSensitiveWordService;
import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.stereotype.Service;
import java.util.List;
@@ -25,8 +26,6 @@ import java.util.List;
@RequiredArgsConstructor
public class SysSensitiveWordServiceImpl extends ServiceImpl<SysSensitiveWordMapper, SysSensitiveWordEntity> implements SysSensitiveWordService {
private final RedisTemplate<String, Object> redisTemplate;
/**
* 查询敏感词
*
@@ -59,7 +58,10 @@ public class SysSensitiveWordServiceImpl extends ServiceImpl<SysSensitiveWordMap
});
}
redisTemplate.convertAndSend(CacheConstants.SENSITIVE_REDIS_RELOAD_TOPIC, "刷新敏感词缓存");
RedisUtils.execute((RedisCallback<Void>) connection -> {
connection.publish(CacheConstants.SENSITIVE_REDIS_RELOAD_TOPIC.getBytes(), "刷新敏感词缓存".getBytes());
return null;
});
return Boolean.TRUE;
}
}
@@ -33,6 +33,7 @@ import com.pig4cloud.pigx.admin.service.*;
import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.core.util.SpringContextHolder;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import com.pig4cloud.pigx.common.data.datascope.DataScopeTypeEnum;
import com.pig4cloud.pigx.common.data.resolver.ParamResolver;
import com.pig4cloud.pigx.common.data.tenant.TenantBroker;
@@ -43,7 +44,6 @@ import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
@@ -54,12 +54,12 @@ import java.time.LocalDateTime;
import java.util.*;
/**
* 租户
* 租户服务实现类
* <p>
* mybatis-plus 3.4.3.3 特殊处理 https://github.com/baomidou/mybatis-plus/pull/3592
* 提供租户相关的业务逻辑实现,包括租户的增删改查及初始化操作
*
* @author lengleng
* @date 2019-05-15 15:55:41
* @date 2025/06/30
*/
@Service
@AllArgsConstructor
@@ -89,8 +89,6 @@ public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant
private final SysTenantUserMapper tenantUserMapper;
private final RedisTemplate redisTemplate;
/**
* 获取正常状态租户
* <p>
@@ -302,9 +300,9 @@ public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant
}
// 清空指定租户的菜单权限缓存
Set keys = redisTemplate.keys(String.format("%s:%s::*", tenantDTO.getId(), CacheConstants.MENU_DETAILS));
Set<String> keys = RedisUtils.keys(String.format("%s:%s::*", tenantDTO.getId(), CacheConstants.MENU_DETAILS));
if (CollUtil.isNotEmpty(keys)) {
redisTemplate.delete(keys);
RedisUtils.delete(keys.toArray(new String[0]));
}
return Boolean.TRUE;
}
@@ -20,7 +20,6 @@
package com.pig4cloud.pigx.admin.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -165,34 +164,32 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
}
/**
* 查询用户全部信息,包括角色和权限
* 根据用户信息查询用户全部信息,包括角色和权限
*
* @param sysUser 用户信息
* @param userDTO 用户信息DTO
* @return 包含用户角色和权限的用户信息对象
*/
@Override
public UserInfo findUserInfo(SysUser sysUser) {
UserInfo userInfo = new UserInfo();
userInfo.setSysUser(sysUser);
public R<UserInfo> getUserInfo(UserDTO userDTO) {
UserVO dbUser = baseMapper.getUserVo(userDTO);
if (dbUser == null) {
return R.failed(MsgUtils.getMessage(ErrorCodes.SYS_USER_USERINFO_EMPTY, userDTO.getUsername()));
}
// 设置角色列表 (ID)
List<Long> roleIds = sysRoleService.findRolesByUserId(sysUser.getUserId())
UserInfo userInfo = new UserInfo();
BeanUtils.copyProperties(dbUser, userInfo);
// 设置权限列表(menu.permission)
List<String> permissions = dbUser.getRoleList()
.stream()
.map(SysRole::getRoleId)
.flatMap(roleId -> sysMenuService.findMenuByRoleId(roleId).stream())
.filter(menu -> StrUtil.isNotEmpty(menu.getPermission()))
.map(SysMenu::getPermission)
.toList();
userInfo.setRoles(ArrayUtil.toArray(roleIds, Long.class));
// 设置权限列表(menu.permission)
Set<String> permissions = new HashSet<>();
roleIds.forEach(roleId -> {
List<String> permissionList = sysMenuService.findMenuByRoleId(roleId)
.stream()
.filter(menu -> StrUtil.isNotEmpty(menu.getPermission()))
.map(SysMenu::getPermission)
.toList();
permissions.addAll(permissionList);
});
userInfo.setPermissions(ArrayUtil.toArray(permissions, String.class));
return userInfo;
userInfo.setPermissions(permissions);
return R.ok(userInfo);
}
/**
@@ -25,6 +25,7 @@
<result column="password_expire_flag" property="passwordExpireFlag"/>
<result column="password_modify_time" property="passwordModifyTime"/>
<result column="del_flag" property="delFlag"/>
<result column="tenant_id" property="tenantId"/>
<collection property="deptList" ofType="com.pig4cloud.pigx.admin.api.entity.SysDept"
select="com.pig4cloud.pigx.admin.mapper.SysDeptMapper.listDeptsByUserId"
column="{userId=user_id, tenantId=tenant_id}">
@@ -65,12 +66,35 @@
u.update_time
</sql>
<select id="getUserVoByUsername" resultMap="baseResultMap">
<select id="getUserVo" resultMap="baseResultMap">
SELECT
<include refid="userColumns"/>
FROM
sys_user u
WHERE u.username = #{username} and u.del_flag = '0'
FROM sys_user u
WHERE u.del_flag = '0'
<if test="query.username != null and query.username != ''">
AND u.username = #{query.username}
</if>
<if test="query.oscId != null and query.oscId != ''">
AND u.osc_id = #{query.oscId}
</if>
<if test="query.phone != null and query.phone != ''">
AND u.phone = #{query.phone}
</if>
<if test="query.wxCpUserid != null and query.wxCpUserid != ''">
AND u.wx_cp_userid = #{query.wxCpUserid}
</if>
<if test="query.wxDingUserid != null and query.wxDingUserid != ''">
AND u.wx_ding_userid = #{query.wxDingUserid}
</if>
<if test="query.giteeLogin != null and query.giteeLogin != ''">
AND u.gitee_login = #{query.giteeLogin}
</if>
<if test="query.wxOpenid != null and query.wxOpenid != ''">
AND u.wx_openid = #{query.wxOpenid}
</if>
<if test="query.miniOpenid != null and query.miniOpenid != ''">
AND u.mini_openid = #{query.miniOpenid}
</if>
</select>
<select id="getUserVoById" resultMap="baseResultMap">
@@ -16,11 +16,9 @@
package com.pig4cloud.pigx.mp.config;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import me.chanjar.weixin.common.enums.TicketType;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.concurrent.TimeUnit;
/**
* @author lengleng
@@ -36,16 +34,13 @@ public class WxMpInRedisConfigStorage extends WxMpDefaultConfigImpl {
private final static String CARDAPI_TICKET_KEY = "wechat:cardapi_ticket_";
private final RedisTemplate<String, String> redisTemplate;
private String accessTokenKey;
private String jsapiTicketKey;
private String cardapiTicketKey;
public WxMpInRedisConfigStorage(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
public WxMpInRedisConfigStorage() {
}
/**
@@ -62,52 +57,52 @@ public class WxMpInRedisConfigStorage extends WxMpDefaultConfigImpl {
@Override
public String getAccessToken() {
return redisTemplate.opsForValue().get(this.accessTokenKey);
return RedisUtils.get(this.accessTokenKey);
}
@Override
public boolean isAccessTokenExpired() {
return redisTemplate.getExpire(accessTokenKey) < 2L;
return RedisUtils.getExpire(accessTokenKey) < 2L;
}
@Override
public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) {
redisTemplate.opsForValue().set(accessTokenKey, accessToken, expiresInSeconds - 200, TimeUnit.SECONDS);
RedisUtils.set(accessTokenKey, accessToken, expiresInSeconds - 200);
}
@Override
public void expireAccessToken() {
redisTemplate.expire(this.accessTokenKey, 0, TimeUnit.SECONDS);
RedisUtils.expire(this.accessTokenKey, 0);
}
@Override
public String getJsapiTicket() {
return redisTemplate.opsForValue().get(this.jsapiTicketKey);
return RedisUtils.get(this.jsapiTicketKey);
}
@Override
public String getCardApiTicket() {
return redisTemplate.opsForValue().get(cardapiTicketKey);
return RedisUtils.get(cardapiTicketKey);
}
@Override
public String getTicket(TicketType type) {
return redisTemplate.opsForValue().get(getTicketRedisKey(type));
return RedisUtils.get(getTicketRedisKey(type));
}
@Override
public boolean isTicketExpired(TicketType type) {
return redisTemplate.getExpire(this.getTicketRedisKey(type)) < 2;
return RedisUtils.getExpire(this.getTicketRedisKey(type)) < 2;
}
@Override
public synchronized void updateTicket(TicketType type, String jsapiTicket, int expiresInSeconds) {
redisTemplate.opsForValue().set(getTicketRedisKey(type), jsapiTicket, expiresInSeconds - 200, TimeUnit.SECONDS);
RedisUtils.set(getTicketRedisKey(type), jsapiTicket, expiresInSeconds - 200);
}
@Override
public void expireTicket(TicketType type) {
redisTemplate.expire(getTicketRedisKey(type), 0, TimeUnit.SECONDS);
RedisUtils.expire(getTicketRedisKey(type), 0);
}
private String getTicketRedisKey(TicketType type) {
@@ -20,7 +20,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.scheduling.annotation.Async;
@@ -83,8 +82,6 @@ public class WxMpInitConfigRunner {
private final ScanHandler scanHandler;
private final RedisTemplate redisTemplate;
@Async
@Order
@EventListener({ ApplicationReadyEvent.class })
@@ -105,7 +102,7 @@ public class WxMpInitConfigRunner {
// @formatter:on
mpServices = accountList.stream().map(a -> {
WxMpInRedisConfigStorage configStorage = new WxMpInRedisConfigStorage(redisTemplate);
WxMpInRedisConfigStorage configStorage = new WxMpInRedisConfigStorage();
configStorage.setAppId(a.getAppid());
configStorage.setSecret(a.getAppsecret());
configStorage.setToken(a.getToken());
@@ -22,6 +22,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import com.pig4cloud.pigx.common.security.annotation.HasPermission;
import com.pig4cloud.pigx.mp.config.WxMpInitConfigRunner;
@@ -30,7 +31,7 @@ import com.pig4cloud.pigx.mp.service.WxAccountService;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import me.chanjar.weixin.mp.api.WxMpService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.web.bind.annotation.*;
/**
@@ -46,8 +47,6 @@ public class WxAccountController {
private final WxAccountService wxAccountService;
private final RedisTemplate redisTemplate;
/**
* 分页查询
* @param page 分页对象
@@ -82,7 +81,8 @@ public class WxAccountController {
@HasPermission("mp_wxaccount_add")
public R save(@RequestBody WxAccount wxAccount) {
wxAccountService.save(wxAccount);
redisTemplate.convertAndSend(CacheConstants.MP_REDIS_RELOAD_TOPIC, "重新加载公众号配置");
RedisUtils.execute((RedisCallback<Long>) connection ->
connection.publish(CacheConstants.MP_REDIS_RELOAD_TOPIC.getBytes(), "重新加载公众号配置".getBytes()));
return R.ok();
}
@@ -96,7 +96,8 @@ public class WxAccountController {
@HasPermission("mp_wxaccount_edit")
public R updateById(@RequestBody WxAccount wxAccount) {
wxAccountService.updateById(wxAccount);
redisTemplate.convertAndSend(CacheConstants.MP_REDIS_RELOAD_TOPIC, "重新加载公众号配置");
RedisUtils.execute((RedisCallback<Long>) connection ->
connection.publish(CacheConstants.MP_REDIS_RELOAD_TOPIC.getBytes(), "重新加载公众号配置".getBytes()));
return R.ok();
}
@@ -110,7 +111,8 @@ public class WxAccountController {
@HasPermission("mp_wxaccount_del")
public R removeById(@PathVariable Long id) {
wxAccountService.removeById(id);
redisTemplate.convertAndSend(CacheConstants.MP_REDIS_RELOAD_TOPIC, "重新加载公众号配置");
RedisUtils.execute((RedisCallback<Long>) connection ->
connection.publish(CacheConstants.MP_REDIS_RELOAD_TOPIC.getBytes(), "重新加载公众号配置".getBytes()));
return R.ok();
}