From bcde35a670db1d5e33d1e187e9d6deaed985ce44 Mon Sep 17 00:00:00 2001 From: ruying408 <1877972603@qq.com> Date: Sun, 4 Aug 2024 00:43:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9Aapp=E7=AB=AF?= =?UTF-8?q?=E9=89=B4=E6=9D=83=EF=BC=8C=E6=89=8B=E6=9C=BA=E5=AF=86=E7=A0=81?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E5=92=8C=E6=89=8B=E6=9C=BA=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E7=A0=81=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 4 + .../com/cool/core/enums/UserTypeEnum.java | 10 + .../core/exception/CoolPreconditions.java | 4 + .../JwtAuthenticationTokenFilter.java | 122 ++++++++++++ .../cool/core/security/JwtSecurityConfig.java | 6 +- .../cool/core/security/jwt/JwtTokenUtil.java | 50 ++++- .../com/cool/core/security/jwt/JwtUser.java | 34 +++- .../com/cool/core/util/CoolSecurityUtil.java | 102 ++++++++++ .../cool/core/util/DatabaseDialectUtils.java | 47 +++++ .../java/com/cool/core/util/EntityUtils.java | 24 +++ .../admin/AdminBaseCommController.java | 1 + .../admin/sys/AdminBaseSysRoleController.java | 11 +- .../base/security/CoolSecurityUtil.java | 63 ------ .../JwtAuthenticationTokenFilter.java | 89 --------- .../security/JwtUserDetailsServiceImpl.java | 2 +- .../security/MySecurityMetadataSource.java | 9 +- .../base/service/sys/BaseSysLoginService.java | 5 + .../impl/BaseSysDepartmentServiceImpl.java | 6 +- .../sys/impl/BaseSysLogServiceImpl.java | 6 +- .../sys/impl/BaseSysLoginServiceImpl.java | 115 ++++++----- .../sys/impl/BaseSysMenuServiceImpl.java | 6 +- .../sys/impl/BaseSysPermsServiceImpl.java | 13 +- .../sys/impl/BaseSysRoleServiceImpl.java | 16 +- .../sys/impl/BaseSysUserServiceImpl.java | 41 ++-- .../cool/modules/recycle/aop/AopConfig.java | 15 -- .../modules/recycle/aop/DeleteAspect.java | 8 +- .../controller/app/AppUserInfoController.java | 14 +- .../app/AppUserLoginController.java | 180 ++++++++++++++++++ .../controller/app/params/CaptchaParam.java | 12 ++ .../controller/app/params/LoginParam.java | 34 ++++ .../app/params/RefreshTokenParam.java | 13 ++ .../controller/app/params/SmsCodeParam.java | 12 ++ .../modules/user/entity/UserInfoEntity.java | 19 +- .../modules/user/service/UserInfoService.java | 2 +- .../user/service/UserLoginService.java | 26 +++ .../service/impl/UserInfoServiceImpl.java | 2 +- .../service/impl/UserLoginServiceImpl.java | 129 ++++++++++--- .../user/token/UserTokenInterceptor.java | 53 ------ .../modules/user/token/UserWebConfig.java | 21 -- .../cool/modules/user/util/UserSmsUtil.java | 38 ++-- src/main/resources/application.yml | 8 +- 41 files changed, 936 insertions(+), 436 deletions(-) create mode 100644 src/main/java/com/cool/core/enums/UserTypeEnum.java create mode 100644 src/main/java/com/cool/core/security/JwtAuthenticationTokenFilter.java create mode 100644 src/main/java/com/cool/core/util/CoolSecurityUtil.java create mode 100644 src/main/java/com/cool/core/util/DatabaseDialectUtils.java delete mode 100644 src/main/java/com/cool/modules/base/security/CoolSecurityUtil.java delete mode 100644 src/main/java/com/cool/modules/base/security/JwtAuthenticationTokenFilter.java delete mode 100644 src/main/java/com/cool/modules/recycle/aop/AopConfig.java create mode 100644 src/main/java/com/cool/modules/user/controller/app/AppUserLoginController.java create mode 100644 src/main/java/com/cool/modules/user/controller/app/params/CaptchaParam.java create mode 100644 src/main/java/com/cool/modules/user/controller/app/params/LoginParam.java create mode 100644 src/main/java/com/cool/modules/user/controller/app/params/RefreshTokenParam.java create mode 100644 src/main/java/com/cool/modules/user/controller/app/params/SmsCodeParam.java delete mode 100644 src/main/java/com/cool/modules/user/token/UserTokenInterceptor.java delete mode 100644 src/main/java/com/cool/modules/user/token/UserWebConfig.java diff --git a/pom.xml b/pom.xml index 3d6a9d1..215df68 100644 --- a/pom.xml +++ b/pom.xml @@ -128,6 +128,10 @@ com.fasterxml.jackson.core jackson-databind + + org.springframework.boot + spring-boot-starter-actuator + diff --git a/src/main/java/com/cool/core/enums/UserTypeEnum.java b/src/main/java/com/cool/core/enums/UserTypeEnum.java new file mode 100644 index 0000000..a35be7c --- /dev/null +++ b/src/main/java/com/cool/core/enums/UserTypeEnum.java @@ -0,0 +1,10 @@ +package com.cool.core.enums; + +/** + * 用户类型 + */ +public enum UserTypeEnum { + ADMIN, // 后台 + APP, // app + UNKNOWN, // 未知 +} diff --git a/src/main/java/com/cool/core/exception/CoolPreconditions.java b/src/main/java/com/cool/core/exception/CoolPreconditions.java index ebb6ade..5767b2e 100644 --- a/src/main/java/com/cool/core/exception/CoolPreconditions.java +++ b/src/main/java/com/cool/core/exception/CoolPreconditions.java @@ -49,6 +49,10 @@ public class CoolPreconditions { check(ObjectUtil.isEmpty(object), formatMessage(message, arguments)); } + public static void checkEmpty(Object object) { + check(ObjectUtil.isEmpty(object), "参数不能为空"); + } + private static String formatMessage(String messagePattern, Object... arguments) { StringBuilder sb = new StringBuilder(); int argumentIndex = 0; diff --git a/src/main/java/com/cool/core/security/JwtAuthenticationTokenFilter.java b/src/main/java/com/cool/core/security/JwtAuthenticationTokenFilter.java new file mode 100644 index 0000000..1021148 --- /dev/null +++ b/src/main/java/com/cool/core/security/JwtAuthenticationTokenFilter.java @@ -0,0 +1,122 @@ +package com.cool.core.security; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.jwt.JWT; +import com.cool.core.annotation.TokenIgnore; +import com.cool.core.cache.CoolCache; +import com.cool.core.enums.UserTypeEnum; +import com.cool.core.security.jwt.JwtTokenUtil; +import com.cool.core.security.jwt.JwtUser; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Objects; +import lombok.RequiredArgsConstructor; +import org.springframework.core.annotation.Order; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerExecutionChain; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + +/** + * Token过滤器 + */ +@Order(1) +@Component +@RequiredArgsConstructor +public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { + + final private JwtTokenUtil jwtTokenUtil; + final private CoolCache coolCache; + private final RequestMappingHandlerMapping requestMappingHandlerMapping; + + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, + FilterChain chain) + throws ServletException, IOException { + try { + HandlerExecutionChain handlerExecutionChain = requestMappingHandlerMapping.getHandler(request); + if (handlerExecutionChain != null) { + Object handler = handlerExecutionChain.getHandler(); + if (handler instanceof HandlerMethod) { + HandlerMethod handlerMethod = (HandlerMethod) handler; + if (handlerMethod.getMethodAnnotation(TokenIgnore.class) != null || + handlerMethod.getBeanType().getAnnotation(TokenIgnore.class) != null) { + chain.doFilter(request, response); + return; + } + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + String authToken = request.getHeader("Authorization"); + if (!StrUtil.isEmpty(authToken)) { + JWT jwt = jwtTokenUtil.getTokenInfo(authToken); + + Object userType = jwt.getPayload("userType"); + if (Objects.equals(userType, UserTypeEnum.APP.name())) { + // app + handlerAppRequest(request, jwt, authToken); + } else { + // admin + handlerAdminRequest(request, jwt, authToken); + } + } + chain.doFilter(request, response); + } + /** + * 处理app请求 + */ + private void handlerAppRequest(HttpServletRequest request, JWT jwt, String authToken) { + String userId = jwt.getPayload("userId").toString(); + if (ObjectUtil.isNotEmpty(userId) + && SecurityContextHolder.getContext().getAuthentication() == null) { + UserDetails userDetails = coolCache.get("app:userDetails:" + userId, + JwtUser.class); + if (jwtTokenUtil.validateToken(authToken) && userDetails != null) { + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( + userDetails, null, userDetails.getAuthorities()); + authentication.setDetails( + new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authentication); + } + } + } + + /** + * 处理后台请求 + */ + private void handlerAdminRequest(HttpServletRequest request, JWT jwt, String authToken) { + String username = jwt.getPayload("username").toString(); + if (username != null + && SecurityContextHolder.getContext().getAuthentication() == null) { + UserDetails userDetails = coolCache.get("admin:userDetails:" + username, + JwtUser.class); + Integer passwordV = Convert.toInt(jwt.getPayload("passwordVersion")); + Integer rv = coolCache.get("admin:passwordVersion:" + jwt.getPayload("userId"), + Integer.class); + if (jwtTokenUtil.validateToken(authToken, username) && Objects.equals(passwordV, rv) + && userDetails != null) { + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( + userDetails, null, userDetails.getAuthorities()); + authentication.setDetails( + new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authentication); + request.setAttribute("adminUsername", jwt.getPayload("username")); + request.setAttribute("adminUserId", jwt.getPayload("userId")); + request.setAttribute("tokenInfo", jwt); + } + } + } +} diff --git a/src/main/java/com/cool/core/security/JwtSecurityConfig.java b/src/main/java/com/cool/core/security/JwtSecurityConfig.java index 39774c8..fc28b65 100644 --- a/src/main/java/com/cool/core/security/JwtSecurityConfig.java +++ b/src/main/java/com/cool/core/security/JwtSecurityConfig.java @@ -1,14 +1,13 @@ package com.cool.core.security; import com.cool.core.annotation.TokenIgnore; -import com.cool.modules.base.security.JwtAuthenticationTokenFilter; +import com.cool.core.enums.UserTypeEnum; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Map; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.AnnotatedElementUtils; @@ -51,7 +50,7 @@ public class JwtSecurityConfig { final private RequestMappingHandlerMapping requestMappingHandlerMapping; @Bean - public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity, ApplicationContext applicationContext) throws Exception { + public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception { // 动态获取忽略的URL configureIgnoredUrls(); @@ -62,6 +61,7 @@ public class JwtSecurityConfig { ignoredUrlsProperties.getAdminAuthUrls().toArray(String[]::new)) .permitAll(); conf.requestMatchers("/admin/**").authenticated(); + conf.requestMatchers("/app/**").hasRole(UserTypeEnum.APP.name()); }) .headers(config -> config.frameOptions(FrameOptionsConfig::disable)) // 允许网页iframe diff --git a/src/main/java/com/cool/core/security/jwt/JwtTokenUtil.java b/src/main/java/com/cool/core/security/jwt/JwtTokenUtil.java index 4e3eec0..5335726 100644 --- a/src/main/java/com/cool/core/security/jwt/JwtTokenUtil.java +++ b/src/main/java/com/cool/core/security/jwt/JwtTokenUtil.java @@ -1,16 +1,16 @@ package com.cool.core.security.jwt; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.jwt.JWT; import cn.hutool.jwt.JWTUtil; import cn.hutool.jwt.JWTValidator; import com.cool.core.config.CoolProperties; +import com.cool.modules.base.service.sys.BaseSysConfService; import java.io.Serializable; import java.util.Date; import java.util.Map; - -import com.cool.modules.base.service.sys.BaseSysConfService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @@ -23,7 +23,8 @@ public class JwtTokenUtil implements Serializable { final private CoolProperties coolProperties; final private BaseSysConfService baseSysConfService; - final String key = "JWT_SECRET"; + final String tokenKey = "JWT_SECRET_TOKEN"; + final String refreshTokenKey = "JWT_SECRET_REFRESH_TOKEN"; public long getExpire() { return this.coolProperties.getToken().getExpire(); @@ -33,11 +34,20 @@ public class JwtTokenUtil implements Serializable { return this.coolProperties.getToken().getRefreshExpire(); } - public String getSecret() { - String secret = baseSysConfService.getValueWithCache(key); + public String getTokenSecret() { + String secret = baseSysConfService.getValueWithCache(tokenKey); if (StrUtil.isBlank(secret)) { secret = StrUtil.uuid().replaceAll("-", ""); - baseSysConfService.setValue(key, secret); + baseSysConfService.setValue(tokenKey, secret); + } + return secret; + } + + public String getRefreshTokenSecret() { + String secret = baseSysConfService.getValueWithCache(refreshTokenKey); + if (StrUtil.isBlank(secret)) { + secret = StrUtil.uuid().replaceAll("-", ""); + baseSysConfService.setValue(refreshTokenKey, secret); } return secret; } @@ -51,7 +61,7 @@ public class JwtTokenUtil implements Serializable { public String generateToken(Map tokenInfo) { tokenInfo.put("isRefresh", false); Date expirationDate = new Date(System.currentTimeMillis() + getExpire() * 1000); - JWT jwt = JWT.create().setExpiresAt(expirationDate).setKey(getSecret().getBytes()) + JWT jwt = JWT.create().setExpiresAt(expirationDate).setKey(getTokenSecret().getBytes()) .setPayload("created", new Date()); tokenInfo.forEach(jwt::setPayload); return jwt.sign(); @@ -66,7 +76,7 @@ public class JwtTokenUtil implements Serializable { public String generateRefreshToken(Map tokenInfo) { tokenInfo.put("isRefresh", true); Date expirationDate = new Date(System.currentTimeMillis() + getRefreshExpire() * 1000); - JWT jwt = JWT.create().setExpiresAt(expirationDate).setKey(getSecret().getBytes()) + JWT jwt = JWT.create().setExpiresAt(expirationDate).setKey(getRefreshTokenSecret().getBytes()) .setPayload("created", new Date()); tokenInfo.forEach(jwt::setPayload); return jwt.sign(); @@ -116,8 +126,11 @@ public class JwtTokenUtil implements Serializable { * @return 是否有效 */ public Boolean validateToken(String token, String username) { + if (ObjectUtil.isEmpty(token)) { + return false; + } String tokenUsername = getUsernameFromToken(token); - String secret = getSecret(); + String secret = getTokenSecret(); boolean isValidSignature = JWTUtil.verify(token, secret.getBytes()); return (tokenUsername.equals(username) && !isTokenExpired(token) && isValidSignature); } @@ -128,7 +141,24 @@ public class JwtTokenUtil implements Serializable { * @return */ public Boolean validateToken(String token) { - String secret = getSecret(); + if (ObjectUtil.isEmpty(token)) { + return false; + } + String secret = getTokenSecret(); + boolean isValidSignature = JWTUtil.verify(token, secret.getBytes()); + return (!isTokenExpired(token) && isValidSignature); + } + + /** + * 校验refresh token是否有效 + * @param token + * @return + */ + public Boolean validateRefreshToken(String token) { + if (ObjectUtil.isEmpty(token)) { + return false; + } + String secret = getRefreshTokenSecret(); boolean isValidSignature = JWTUtil.verify(token, secret.getBytes()); return (!isTokenExpired(token) && isValidSignature); } diff --git a/src/main/java/com/cool/core/security/jwt/JwtUser.java b/src/main/java/com/cool/core/security/jwt/JwtUser.java index bddcfa7..c69cf9e 100644 --- a/src/main/java/com/cool/core/security/jwt/JwtUser.java +++ b/src/main/java/com/cool/core/security/jwt/JwtUser.java @@ -1,29 +1,45 @@ package com.cool.core.security.jwt; +import com.cool.core.enums.UserTypeEnum; +import java.util.Collection; +import java.util.List; import lombok.Data; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; -import java.util.Collection; -import java.util.List; - /** - * 用户信息 + * 后台用户信息 */ @Data public class JwtUser implements UserDetails { - public JwtUser(String username, String password, List perms, Boolean status) { + /****** + * 后台用户 + * ********/ + private Long userId; + private String username; + private String password; + private Boolean status; + private UserTypeEnum userTypeEnum; + private List perms; + public JwtUser(Long userId, String username, String password, List perms, Boolean status) { + this.userId = userId; this.username = username; this.password = password; this.perms = perms; this.status = status; + this.userTypeEnum = UserTypeEnum.ADMIN; } - private String username; - private String password; - private Boolean status; - private List perms; + /****** + * app用户 + * ********/ + public JwtUser(Long userId, List perms, Boolean status) { + this.userId = userId; + this.perms = perms; + this.status = status; + this.userTypeEnum = UserTypeEnum.APP; + } @Override public Collection getAuthorities() { diff --git a/src/main/java/com/cool/core/util/CoolSecurityUtil.java b/src/main/java/com/cool/core/util/CoolSecurityUtil.java new file mode 100644 index 0000000..90ee147 --- /dev/null +++ b/src/main/java/com/cool/core/util/CoolSecurityUtil.java @@ -0,0 +1,102 @@ +package com.cool.core.util; + +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONObject; +import com.cool.core.cache.CoolCache; +import com.cool.core.enums.UserTypeEnum; +import com.cool.core.exception.CoolPreconditions; +import com.cool.core.security.jwt.JwtUser; +import com.cool.modules.base.entity.sys.BaseSysUserEntity; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; + +/** + * Security 工具类 + */ +public class CoolSecurityUtil { + + private static final CoolCache coolCache = SpringUtil.getBean(CoolCache.class); + + /***************后台********************/ + /** + * 获取后台登录的用户名 + */ + public static String getAdminUsername() { + return SecurityContextHolder.getContext().getAuthentication().getName(); + } + + /** + * 获得jwt中的信息 + * + * @param requestParams 请求参数 + * @return jwt + */ + public static JSONObject getAdminUserInfo(JSONObject requestParams) { + JSONObject tokenInfo = requestParams.getJSONObject("tokenInfo"); + if (tokenInfo != null) { + tokenInfo.set("department", + coolCache.get("admin:department:" + tokenInfo.get("userId"))); + tokenInfo.set("roleIds", coolCache.get("admin:roleIds:" + tokenInfo.get("userId"))); + } + return tokenInfo; + } + + /** + * 后台账号退出登录 + * + * @param adminUserId 用户ID + * @param username 用户名 + */ + public static void adminLogout(Long adminUserId, String username) { + coolCache.del("admin:department:" + adminUserId, "admin:passwordVersion:" + adminUserId, + "admin:userInfo:" + adminUserId, "admin:userDetails:" + username); + } + + /** + * 后台账号退出登录 + * + * @param userEntity 用户 + */ + public static void adminLogout(BaseSysUserEntity userEntity) { + adminLogout(userEntity.getId(), userEntity.getUsername()); + } + + + /** + * 获取当前用户id + */ + public static Long getCurrentUserId() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication != null) { + Object principal = authentication.getPrincipal(); + if (principal instanceof UserDetails) { + return ((JwtUser) principal).getUserId(); + } + } + CoolPreconditions.check(true, 401, "未登录"); + return null; + } + + /** + * 获取当前用户类型 + */ + public static UserTypeEnum getCurrentUserType() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication != null) { + Object principal = authentication.getPrincipal(); + if (principal instanceof UserDetails) { + return ((JwtUser) principal).getUserTypeEnum(); + } + } + // 还未登录,未知类型 + return UserTypeEnum.UNKNOWN; + } + + /** + * app退出登录,移除缓存信息 + */ + public static void appLogout() { + coolCache.del("app:userDetails"+ getCurrentUserId()); + } +} diff --git a/src/main/java/com/cool/core/util/DatabaseDialectUtils.java b/src/main/java/com/cool/core/util/DatabaseDialectUtils.java new file mode 100644 index 0000000..e49432e --- /dev/null +++ b/src/main/java/com/cool/core/util/DatabaseDialectUtils.java @@ -0,0 +1,47 @@ +package com.cool.core.util; +import com.cool.core.exception.CoolPreconditions; +import com.tangzc.autotable.core.constants.DatabaseDialect; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; +import javax.sql.DataSource; + +/** + * 获取数据库方言 + */ +public class DatabaseDialectUtils { + private static String dialect; + + public static String getDatabaseDialect() { + if (dialect == null) { + dialect = determineDatabaseType(); + } + return dialect; + } + + private static String determineDatabaseType() { + // 从 DataSource 获取连接 + DataSource dataSource = SpringContextUtils.getBean(DataSource.class); + try (Connection connection = dataSource.getConnection()) { + // 获取元数据 + DatabaseMetaData metaData = connection.getMetaData(); + String productName = metaData.getDatabaseProductName(); + + return inferDatabaseTypeFromProductName(productName); + } catch (SQLException e) { + throw new RuntimeException("Failed to determine database dialect", e); + } + } + + private static String inferDatabaseTypeFromProductName(String productName) { + if (productName.startsWith(DatabaseDialect.MySQL)) { + return DatabaseDialect.MySQL; + } else if (productName.startsWith(DatabaseDialect.PostgreSQL)) { + return DatabaseDialect.PostgreSQL; + } else if (productName.startsWith(DatabaseDialect.SQLite)) { + return DatabaseDialect.SQLite; + } + CoolPreconditions.alwaysThrow("暂不支持!"); + return "unknown"; + } +} diff --git a/src/main/java/com/cool/core/util/EntityUtils.java b/src/main/java/com/cool/core/util/EntityUtils.java index 6bb418f..2657b04 100644 --- a/src/main/java/com/cool/core/util/EntityUtils.java +++ b/src/main/java/com/cool/core/util/EntityUtils.java @@ -1,6 +1,9 @@ package com.cool.core.util; import cn.hutool.core.annotation.AnnotationUtil; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Editor; import cn.hutool.core.util.ObjUtil; import com.mybatisflex.annotation.Table; import com.mybatisflex.core.query.QueryColumn; @@ -9,6 +12,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -78,6 +82,26 @@ public class EntityUtils { .filter(o -> !excludeList.contains(o.getName())).toList(); } + /** + * 将bean的部分属性转换成map
+ * 可选拷贝哪些属性值,默认是不忽略值为{@code null}的值的。 + * + * @param bean bean + * @param ignoreProperties 需要忽略拷贝的属性值,{@code null}或空表示拷贝所有值 + * @return Map + * @since 5.8.0 + */ + public static Map toMap(Object bean, String... ignoreProperties) { + int mapSize = 16; + Editor keyEditor = null; + final Set propertiesSet = CollUtil.set(false, ignoreProperties); + propertiesSet.add("queryWrapper"); + mapSize = ignoreProperties.length; + keyEditor = property -> !propertiesSet.contains(property) ? property : null; + // 指明了要复制的属性 所以不忽略null值 + return BeanUtil.beanToMap(bean, new LinkedHashMap<>(mapSize, 1), false, keyEditor); + } + /** * 检查字段名是否在排除列表中 * diff --git a/src/main/java/com/cool/modules/base/controller/admin/AdminBaseCommController.java b/src/main/java/com/cool/modules/base/controller/admin/AdminBaseCommController.java index cbfd918..8e1fc59 100644 --- a/src/main/java/com/cool/modules/base/controller/admin/AdminBaseCommController.java +++ b/src/main/java/com/cool/modules/base/controller/admin/AdminBaseCommController.java @@ -92,6 +92,7 @@ public class AdminBaseCommController { return R.ok(); } + @TokenIgnore @Operation(summary = "编程") @GetMapping("/program") public R program() { diff --git a/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysRoleController.java b/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysRoleController.java index 86d6b58..acbf938 100644 --- a/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysRoleController.java +++ b/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysRoleController.java @@ -1,15 +1,17 @@ package com.cool.modules.base.controller.admin.sys; +import static com.cool.modules.base.entity.sys.table.BaseSysRoleEntityTableDef.BASE_SYS_ROLE_ENTITY; + +import cn.hutool.json.JSONArray; import cn.hutool.json.JSONObject; import com.cool.core.annotation.CoolRestController; import com.cool.core.base.BaseController; import com.cool.modules.base.entity.sys.BaseSysRoleEntity; -import static com.cool.modules.base.entity.sys.table.BaseSysRoleEntityTableDef.BASE_SYS_ROLE_ENTITY; import com.cool.modules.base.service.sys.BaseSysRoleService; import com.mybatisflex.core.query.QueryWrapper; import io.swagger.v3.oas.annotations.tags.Tag; - import jakarta.servlet.http.HttpServletRequest; + /** * 系统角色 */ @@ -24,7 +26,10 @@ public class AdminBaseSysRoleController extends BaseController { qw.eq(BASE_SYS_ROLE_ENTITY.USER_ID.getName(), tokenInfo.get("userId")).or(w -> { - w.in(BASE_SYS_ROLE_ENTITY.ID.getName(), tokenInfo.get("roleIds")); + Object o = tokenInfo.get("roleIds"); + if (o != null) { + w.in(BASE_SYS_ROLE_ENTITY.ID.getName(), new JSONArray(o).toList(Long.class)); + } }); }, !isAdmin).and(BASE_SYS_ROLE_ENTITY.LABEL.ne("admin")))); } diff --git a/src/main/java/com/cool/modules/base/security/CoolSecurityUtil.java b/src/main/java/com/cool/modules/base/security/CoolSecurityUtil.java deleted file mode 100644 index 8997937..0000000 --- a/src/main/java/com/cool/modules/base/security/CoolSecurityUtil.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.cool.modules.base.security; - -import cn.hutool.json.JSONObject; -import com.cool.core.cache.CoolCache; -import com.cool.modules.base.entity.sys.BaseSysUserEntity; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Component; - -/** - * Security 工具类 - */ -@Component -@RequiredArgsConstructor -public class CoolSecurityUtil { - - final private CoolCache coolCache; - - /** - * 登录的用户名 - * - * @return 用户名 - */ - public String username() { - return SecurityContextHolder.getContext().getAuthentication().getName(); - } - - /** - * 获得jwt中的信息 - * - * @param requestParams 请求参数 - * @return jwt - */ - public JSONObject userInfo(JSONObject requestParams) { - JSONObject tokenInfo = requestParams.getJSONObject("tokenInfo"); - if (tokenInfo != null) { - tokenInfo.set("department", - coolCache.get("admin:department:" + tokenInfo.get("userId"))); - tokenInfo.set("roleIds", coolCache.get("admin:roleIds:" + tokenInfo.get("userId"))); - } - return tokenInfo; - } - - /** - * 退出登录 - * - * @param adminUserId 用户ID - * @param username 用户名 - */ - public void logout(Long adminUserId, String username) { - coolCache.del("admin:department:" + adminUserId, "admin:passwordVersion:" + adminUserId, - "admin:userInfo:" + adminUserId, "admin:userDetails:" + username); - } - - /** - * 退出登录 - * - * @param userEntity 用户 - */ - public void logout(BaseSysUserEntity userEntity) { - logout(userEntity.getId(), userEntity.getUsername()); - } -} diff --git a/src/main/java/com/cool/modules/base/security/JwtAuthenticationTokenFilter.java b/src/main/java/com/cool/modules/base/security/JwtAuthenticationTokenFilter.java deleted file mode 100644 index cddbbd8..0000000 --- a/src/main/java/com/cool/modules/base/security/JwtAuthenticationTokenFilter.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.cool.modules.base.security; - -import cn.hutool.core.convert.Convert; -import cn.hutool.core.util.StrUtil; -import cn.hutool.jwt.JWT; -import com.cool.core.annotation.TokenIgnore; -import com.cool.core.cache.CoolCache; -import com.cool.core.security.jwt.JwtTokenUtil; -import com.cool.core.security.jwt.JwtUser; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -import java.io.IOException; -import java.util.Objects; - -import lombok.RequiredArgsConstructor; -import org.springframework.core.annotation.Order; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; -import org.springframework.stereotype.Component; -import org.springframework.web.filter.OncePerRequestFilter; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.HandlerExecutionChain; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; - -/** - * Token过滤器 - */ -@Order(1) -@Component -@RequiredArgsConstructor -public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { - - final private JwtTokenUtil jwtTokenUtil; - final private CoolCache coolCache; - private final RequestMappingHandlerMapping handlerMapping; - - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, - FilterChain chain) - throws ServletException, IOException { - try { - HandlerExecutionChain handlerExecutionChain = handlerMapping.getHandler(request); - if (handlerExecutionChain != null) { - Object handler = handlerExecutionChain.getHandler(); - if (handler instanceof HandlerMethod) { - HandlerMethod handlerMethod = (HandlerMethod) handler; - if (handlerMethod.getMethodAnnotation(TokenIgnore.class) != null || - handlerMethod.getBeanType().getAnnotation(TokenIgnore.class) != null) { - chain.doFilter(request, response); - return; - } - } - } - } catch (Exception e) { - throw new RuntimeException(e); - } - String authToken = request.getHeader("Authorization"); - if (!StrUtil.isEmpty(authToken)) { - JWT jwt = jwtTokenUtil.getTokenInfo(authToken); - String username = jwt.getPayload("username").toString(); - if (username != null - && SecurityContextHolder.getContext().getAuthentication() == null) { - UserDetails userDetails = coolCache.get("admin:userDetails:" + username, - JwtUser.class); - Integer passwordV = Convert.toInt(jwt.getPayload("passwordVersion")); - Integer rv = coolCache.get("admin:passwordVersion:" + jwt.getPayload("userId"), - Integer.class); - if (jwtTokenUtil.validateToken(authToken, username) && Objects.equals(passwordV, rv) - && userDetails != null) { - UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( - userDetails, null, userDetails.getAuthorities()); - authentication.setDetails( - new WebAuthenticationDetailsSource().buildDetails(request)); - SecurityContextHolder.getContext().setAuthentication(authentication); - request.setAttribute("adminUsername", jwt.getPayload("username")); - request.setAttribute("adminUserId", jwt.getPayload("userId")); - request.setAttribute("tokenInfo", jwt); - } - } - } - chain.doFilter(request, response); - } -} diff --git a/src/main/java/com/cool/modules/base/security/JwtUserDetailsServiceImpl.java b/src/main/java/com/cool/modules/base/security/JwtUserDetailsServiceImpl.java index 99e5853..574dce7 100644 --- a/src/main/java/com/cool/modules/base/security/JwtUserDetailsServiceImpl.java +++ b/src/main/java/com/cool/modules/base/security/JwtUserDetailsServiceImpl.java @@ -42,7 +42,7 @@ public class JwtUserDetailsServiceImpl implements UserDetailsService { authority.add(new SimpleGrantedAuthority(perm)); } Long[] departmentIds = baseSysPermsService.getDepartmentIdsByRoleIds(sysUserEntity.getId()); - JwtUser jwtUser = new JwtUser(sysUserEntity.getUsername(), sysUserEntity.getPassword(), + JwtUser jwtUser = new JwtUser(sysUserEntity.getId(), sysUserEntity.getUsername(), sysUserEntity.getPassword(), authority, sysUserEntity.getStatus() == 1); Long[] roleIds = baseSysPermsService.getRoles(sysUserEntity); diff --git a/src/main/java/com/cool/modules/base/security/MySecurityMetadataSource.java b/src/main/java/com/cool/modules/base/security/MySecurityMetadataSource.java index 7322d1d..2f97be4 100644 --- a/src/main/java/com/cool/modules/base/security/MySecurityMetadataSource.java +++ b/src/main/java/com/cool/modules/base/security/MySecurityMetadataSource.java @@ -1,5 +1,8 @@ package com.cool.modules.base.security; +import cn.hutool.core.util.ObjectUtil; +import com.cool.core.enums.UserTypeEnum; +import com.cool.core.util.CoolSecurityUtil; import com.cool.modules.base.service.sys.BaseSysPermsService; import java.util.ArrayList; import java.util.Collection; @@ -53,13 +56,17 @@ public class MySecurityMetadataSource implements FilterInvocationSecurityMetadat */ @Override public Collection getAttributes(Object o) throws IllegalArgumentException { + UserTypeEnum userTypeEnum = CoolSecurityUtil.getCurrentUserType(); + if (ObjectUtil.equal(userTypeEnum, UserTypeEnum.APP)) { + // app用户不需要权限拦截 + return null; + } if (map == null) { loadResourceDefine(); } // Object中包含用户请求request String url = ((FilterInvocation) o).getRequestUrl(); return map.get(url.replace("/admin/", "").split("[?]")[0]); - } @Override diff --git a/src/main/java/com/cool/modules/base/service/sys/BaseSysLoginService.java b/src/main/java/com/cool/modules/base/service/sys/BaseSysLoginService.java index 731e45f..7881aad 100644 --- a/src/main/java/com/cool/modules/base/service/sys/BaseSysLoginService.java +++ b/src/main/java/com/cool/modules/base/service/sys/BaseSysLoginService.java @@ -16,6 +16,11 @@ public interface BaseSysLoginService { */ Object captcha(String type, Integer width, Integer height); + /** + * 校验验证码 + */ + void captchaCheck(String captchaId, String code); + /** * 登录 * diff --git a/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysDepartmentServiceImpl.java b/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysDepartmentServiceImpl.java index c666b16..95fa7ea 100644 --- a/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysDepartmentServiceImpl.java +++ b/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysDepartmentServiceImpl.java @@ -2,11 +2,11 @@ package com.cool.modules.base.service.sys.impl; import cn.hutool.json.JSONObject; import com.cool.core.base.BaseServiceImpl; +import com.cool.core.util.CoolSecurityUtil; import com.cool.modules.base.entity.sys.BaseSysDepartmentEntity; import com.cool.modules.base.entity.sys.BaseSysUserEntity; import com.cool.modules.base.mapper.sys.BaseSysDepartmentMapper; import com.cool.modules.base.mapper.sys.BaseSysUserMapper; -import com.cool.modules.base.security.CoolSecurityUtil; import com.cool.modules.base.service.sys.BaseSysDepartmentService; import com.cool.modules.base.service.sys.BaseSysPermsService; import com.mybatisflex.core.query.QueryWrapper; @@ -27,8 +27,6 @@ public class BaseSysDepartmentServiceImpl extends final private BaseSysUserMapper baseSysUserMapper; - final private CoolSecurityUtil coolSecurityUtil; - final private BaseSysPermsService baseSysPermsService; @Override @@ -42,7 +40,7 @@ public class BaseSysDepartmentServiceImpl extends @Override public List list(JSONObject requestParams, QueryWrapper queryWrapper) { - String username = coolSecurityUtil.username(); + String username = CoolSecurityUtil.getAdminUsername(); Long[] loginDepartmentIds = baseSysPermsService.loginDepartmentIds(); if (loginDepartmentIds != null && loginDepartmentIds.length == 0) { return new ArrayList<>(); diff --git a/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysLogServiceImpl.java b/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysLogServiceImpl.java index cf5bdba..decbc4a 100644 --- a/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysLogServiceImpl.java +++ b/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysLogServiceImpl.java @@ -7,13 +7,13 @@ import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.cool.core.base.BaseServiceImpl; import com.cool.core.security.IgnoredUrlsProperties; +import com.cool.core.util.CoolSecurityUtil; import com.cool.core.util.IPUtils; import com.cool.modules.base.entity.sys.BaseSysLogEntity; import com.cool.modules.base.entity.sys.BaseSysUserEntity; import com.cool.modules.base.entity.sys.table.BaseSysLogEntityTableDef; import com.cool.modules.base.entity.sys.table.BaseSysUserEntityTableDef; import com.cool.modules.base.mapper.sys.BaseSysLogMapper; -import com.cool.modules.base.security.CoolSecurityUtil; import com.cool.modules.base.service.sys.BaseSysConfService; import com.cool.modules.base.service.sys.BaseSysLogService; import com.mybatisflex.core.paginate.Page; @@ -35,8 +35,6 @@ public class BaseSysLogServiceImpl extends BaseServiceImpl list = baseSysPermsService.getMenus(coolSecurityUtil.username()); + List list = baseSysPermsService.getMenus(CoolSecurityUtil.getAdminUsername()); list.forEach(e -> { List parent = list.stream() .filter(sysMenuEntity -> e.getParentId() != null && e.getParentId() diff --git a/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysPermsServiceImpl.java b/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysPermsServiceImpl.java index b97e9d3..9b9671b 100644 --- a/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysPermsServiceImpl.java +++ b/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysPermsServiceImpl.java @@ -11,10 +11,10 @@ import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.cool.core.cache.CoolCache; +import com.cool.core.util.CoolSecurityUtil; import com.cool.core.util.SpringContextUtils; import com.cool.modules.base.entity.sys.*; import com.cool.modules.base.mapper.sys.*; -import com.cool.modules.base.security.CoolSecurityUtil; import com.cool.modules.base.service.sys.BaseSysPermsService; import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.row.Row; @@ -41,11 +41,9 @@ public class BaseSysPermsServiceImpl implements BaseSysPermsService { final private BaseSysDepartmentMapper baseSysDepartmentMapper; - final private CoolSecurityUtil coolSecurityUtil; - @Override public Long[] loginDepartmentIds() { - String username = coolSecurityUtil.username(); + String username = CoolSecurityUtil.getAdminUsername(); if (username.equals("admin")) { return baseSysDepartmentMapper.selectAll().stream().map(BaseSysDepartmentEntity::getId) .toArray(Long[]::new); @@ -64,8 +62,11 @@ public class BaseSysPermsServiceImpl implements BaseSysPermsService { } private Long[] getLongs(Long[] roleIds) { + if (ObjectUtil.isEmpty(roleIds)) { + return new Long[]{}; + } QueryWrapper queryWrapper = QueryWrapper.create(); - if (roleIds != null && !CollUtil.toList(roleIds).contains(1L)) { + if (!CollUtil.toList(roleIds).contains(1L)) { queryWrapper.in(BaseSysRoleDepartmentEntity::getRoleId, (Object) roleIds); } return baseSysRoleDepartmentMapper @@ -217,7 +218,7 @@ public class BaseSysPermsServiceImpl implements BaseSysPermsService { SpringContextUtils.getBean(UserDetailsService.class).loadUserByUsername(baseSysUserEntity.getUsername()); } if (baseSysUserEntity != null && baseSysUserEntity.getStatus() == 0) { - coolSecurityUtil.logout(baseSysUserEntity.getId(), baseSysUserEntity.getUsername()); + CoolSecurityUtil.adminLogout(baseSysUserEntity.getId(), baseSysUserEntity.getUsername()); } } diff --git a/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysRoleServiceImpl.java b/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysRoleServiceImpl.java index 8c5a762..d437348 100644 --- a/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysRoleServiceImpl.java +++ b/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysRoleServiceImpl.java @@ -5,21 +5,20 @@ import cn.hutool.json.JSONObject; import com.cool.core.base.BaseServiceImpl; import com.cool.core.base.ModifyEnum; import com.cool.core.exception.CoolException; +import com.cool.core.util.CoolSecurityUtil; import com.cool.modules.base.entity.sys.BaseSysRoleDepartmentEntity; import com.cool.modules.base.entity.sys.BaseSysRoleEntity; import com.cool.modules.base.entity.sys.BaseSysRoleMenuEntity; import com.cool.modules.base.mapper.sys.BaseSysRoleDepartmentMapper; import com.cool.modules.base.mapper.sys.BaseSysRoleMapper; import com.cool.modules.base.mapper.sys.BaseSysRoleMenuMapper; -import com.cool.modules.base.security.CoolSecurityUtil; import com.cool.modules.base.service.sys.BaseSysPermsService; import com.cool.modules.base.service.sys.BaseSysRoleService; import com.mybatisflex.core.query.QueryWrapper; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import java.util.List; - /** * 系统角色 */ @@ -36,15 +35,13 @@ public class BaseSysRoleServiceImpl extends BaseServiceImpl { - qw.eq(BaseSysRoleEntity::getUserId, coolSecurityUtil.userInfo(requestParams).get("userId")).or(w -> { + JSONObject object = CoolSecurityUtil.getAdminUserInfo(requestParams); + qw.eq(BaseSysRoleEntity::getUserId, object.get("userId")).or(w -> { w.in(BaseSysRoleEntity::getId, - (Object) coolSecurityUtil.userInfo(requestParams).get("roleIds", Long[].class)); + (Object) object.get("roleIds", Long[].class)); }); - }, !coolSecurityUtil.username().equals("admin"))); + }, !CoolSecurityUtil.getAdminUsername().equals("admin"))); } } \ No newline at end of file diff --git a/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysUserServiceImpl.java b/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysUserServiceImpl.java index c144c6d..be2f87a 100644 --- a/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysUserServiceImpl.java +++ b/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysUserServiceImpl.java @@ -15,18 +15,19 @@ import com.cool.core.base.BaseServiceImpl; import com.cool.core.base.ModifyEnum; import com.cool.core.cache.CoolCache; import com.cool.core.exception.CoolPreconditions; +import com.cool.core.util.CoolSecurityUtil; +import com.cool.core.util.DatabaseDialectUtils; import com.cool.modules.base.entity.sys.BaseSysDepartmentEntity; import com.cool.modules.base.entity.sys.BaseSysUserEntity; import com.cool.modules.base.mapper.sys.BaseSysDepartmentMapper; import com.cool.modules.base.mapper.sys.BaseSysUserMapper; -import com.cool.modules.base.security.CoolSecurityUtil; import com.cool.modules.base.service.sys.BaseSysPermsService; import com.cool.modules.base.service.sys.BaseSysUserService; import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.update.UpdateChain; +import com.tangzc.autotable.core.constants.DatabaseDialect; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; /** @@ -39,30 +40,27 @@ public class BaseSysUserServiceImpl extends BaseServiceImpl page, QueryWrapper qw) { String keyWord = requestParams.getStr("keyWord"); Integer status = requestParams.getInt("status"); Long[] departmentIds = requestParams.get("departmentIds", Long[].class); - JSONObject tokenInfo = coolSecurityUtil.userInfo(requestParams); + JSONObject tokenInfo = CoolSecurityUtil.getAdminUserInfo(requestParams); // 用户的部门权限 Long[] permsDepartmentArr = coolCache.get("admin:department:" + tokenInfo.get("userId"), Long[].class); - // TODO 临时兼容 postgresql - if (datasourceUrl.contains("postgresql")) { - qw.select(BASE_SYS_USER_ENTITY.ALL_COLUMNS -// , -// groupConcat(BASE_SYS_ROLE_ENTITY.NAME).as("roleName"), -// BASE_SYS_DEPARTMENT_ENTITY.NAME.as("departmentName") + String databaseDialect = DatabaseDialectUtils.getDatabaseDialect(); + if (databaseDialect.equals(DatabaseDialect.PostgreSQL)) { + qw.select("base_sys_user.id","base_sys_user.create_time","base_sys_user.department_id", + "base_sys_user.email","base_sys_user.head_img","base_sys_user.name","base_sys_user.nick_name", + "base_sys_user.phone","base_sys_user.remark","base_sys_user.status", + "base_sys_user.update_time","base_sys_user.username", + "string_agg(base_sys_role.name, ', ') AS roleName", + "base_sys_department.name AS departmentName" ); } else { qw.select(BASE_SYS_USER_ENTITY.ALL_COLUMNS, @@ -94,9 +92,16 @@ public class BaseSysUserServiceImpl extends BaseServiceImpl params, @@ -71,10 +69,10 @@ public class DeleteAspect { if (ObjUtil.isNotEmpty(list)) { RecycleDataEntity recycleDataEntity = new RecycleDataEntity(); recycleDataEntity.setUrl(request.getRequestURI()); - recycleDataEntity.setUserName(coolSecurityUtil.username()); + recycleDataEntity.setUserName(CoolSecurityUtil.getAdminUsername()); recycleDataEntity .setUserId(Long.parseLong( - String.valueOf(coolSecurityUtil.userInfo(requestParams).get("userId")))); + String.valueOf(CoolSecurityUtil.getAdminUserInfo(requestParams).get("userId")))); recycleDataEntity.setParams(params); recycleDataEntity.setData(list); recycleDataEntity.setParams(params); diff --git a/src/main/java/com/cool/modules/user/controller/app/AppUserInfoController.java b/src/main/java/com/cool/modules/user/controller/app/AppUserInfoController.java index 0be0fe3..764e82f 100644 --- a/src/main/java/com/cool/modules/user/controller/app/AppUserInfoController.java +++ b/src/main/java/com/cool/modules/user/controller/app/AppUserInfoController.java @@ -1,23 +1,29 @@ package com.cool.modules.user.controller.app; import com.cool.core.annotation.CoolRestController; +import com.cool.core.request.R; +import com.cool.core.util.CoolSecurityUtil; +import com.cool.core.util.EntityUtils; +import com.cool.modules.user.entity.UserInfoEntity; import com.cool.modules.user.service.UserInfoService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestAttribute; @RequiredArgsConstructor @Tag(name = "用户信息", description = "用户信息") -@CoolRestController() +@CoolRestController public class AppUserInfoController { private final UserInfoService userInfoService; @Operation(summary = "用户个人信息", description = "获得App、小程序或者其他应用的用户个人信息") @GetMapping("/person") - public Object person(@RequestAttribute("appUserId") Long appUserId) { - return userInfoService.person(appUserId); + public R person() { + Long userId = CoolSecurityUtil.getCurrentUserId(); + UserInfoEntity userInfoEntity = userInfoService.person(userId); + return R.ok(EntityUtils.toMap(userInfoEntity, + "password")); } } diff --git a/src/main/java/com/cool/modules/user/controller/app/AppUserLoginController.java b/src/main/java/com/cool/modules/user/controller/app/AppUserLoginController.java new file mode 100644 index 0000000..47d39bf --- /dev/null +++ b/src/main/java/com/cool/modules/user/controller/app/AppUserLoginController.java @@ -0,0 +1,180 @@ +package com.cool.modules.user.controller.app; + +import com.cool.core.annotation.CoolRestController; +import com.cool.core.annotation.TokenIgnore; +import com.cool.core.exception.CoolPreconditions; +import com.cool.core.request.R; +import com.cool.modules.base.service.sys.BaseSysLoginService; +import com.cool.modules.user.controller.app.params.CaptchaParam; +import com.cool.modules.user.controller.app.params.LoginParam; +import com.cool.modules.user.controller.app.params.RefreshTokenParam; +import com.cool.modules.user.controller.app.params.SmsCodeParam; +import com.cool.modules.user.service.UserLoginService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +@RequiredArgsConstructor +@Tag(name = "用户登录", description = "用户登录") +@CoolRestController +public class AppUserLoginController { + + private final UserLoginService userLoginService; + + private final BaseSysLoginService baseSysLoginService; + + /** + * 小程序登录 + */ + @TokenIgnore + @Operation(summary = "小程序登录") + @PostMapping("/mini") + public R mini(@RequestBody LoginParam param) { + String code = param.getCode(); + String encryptedData = param.getEncryptedData(); + String iv = param.getIv(); + CoolPreconditions.checkEmpty(code); + CoolPreconditions.checkEmpty(encryptedData); + CoolPreconditions.checkEmpty(iv); + return R.ok(userLoginService.mini(code, encryptedData, iv)); + } + + /** + * 公众号登录 + */ + @TokenIgnore + @Operation(summary = "公众号登录") + @PostMapping("/mp") + public R mp(@RequestBody LoginParam param) { + String code = param.getCode(); + CoolPreconditions.checkEmpty(code); + return R.ok(userLoginService.mp(code)); + } + + /** + * 微信APP授权登录 + */ + @TokenIgnore + @Operation(summary = "微信APP授权登录") + @PostMapping("/wxApp") + public R wxApp(@RequestBody LoginParam param) { + String code = param.getCode(); + CoolPreconditions.checkEmpty(code); + return R.ok(userLoginService.wxApp(code)); + } + + /** + * 手机号登录 + */ + @TokenIgnore + @Operation(summary = "手机号登录") + @PostMapping("/phone") + public R phone( + @RequestBody LoginParam param) { + String phone = param.getPhone(); + String smsCode = param.getSmsCode(); + CoolPreconditions.checkEmpty(phone); + CoolPreconditions.checkEmpty(smsCode); + return R.ok(userLoginService.phoneVerifyCode(phone, smsCode)); + } + + /** + * 一键手机号登录 + */ + @TokenIgnore + @Operation(summary = "一键手机号登录") + @PostMapping("/uniPhone") + public R uniPhone( + @RequestBody LoginParam param) { + String accessToken = param.getAccess_token(); + String openid = param.getOpenid(); + String appId = param.getAppId(); + CoolPreconditions.checkEmpty(accessToken); + CoolPreconditions.checkEmpty(openid); + CoolPreconditions.checkEmpty(appId); + return R.ok(userLoginService.uniPhone(accessToken, openid, appId)); + } + + /** + * 绑定小程序手机号 + */ + @TokenIgnore + @Operation(summary = "绑定小程序手机号") + @PostMapping("/miniPhone") + public R miniPhone(@RequestBody LoginParam param) { + String code = param.getCode(); + String encryptedData = param.getEncryptedData(); + String iv = param.getIv(); + CoolPreconditions.checkEmpty(code); + CoolPreconditions.checkEmpty(encryptedData); + CoolPreconditions.checkEmpty(iv); + return R.ok(userLoginService.miniPhone(code, encryptedData, iv)); + } + + /** + * 图片验证码 + */ + @TokenIgnore + @Operation(summary = "图片验证码") + @GetMapping("/captcha") + public R captcha( + @RequestBody CaptchaParam param) { + String type = param.getType(); + Integer width = param.getWidth(); + Integer height = param.getHeight(); + + CoolPreconditions.checkEmpty(type); + CoolPreconditions.checkEmpty(width); + CoolPreconditions.checkEmpty(height); + + return R.ok(baseSysLoginService.captcha(type, width, height)); + } + + /** + * 验证码 + */ + @TokenIgnore + @Operation(summary = "验证码") + @PostMapping("/smsCode") + public R smsCode( + @RequestBody SmsCodeParam param) { + String phone = param.getPhone(); + String captchaId = param.getCaptchaId(); + String code = param.getCode(); + + CoolPreconditions.checkEmpty(phone); + CoolPreconditions.checkEmpty(captchaId); + CoolPreconditions.checkEmpty(code); + userLoginService.smsCode(phone, captchaId, code); + return R.ok(); + } + + /** + * 刷新token + */ + @TokenIgnore + @Operation(summary = "刷新token") + @PostMapping("/refreshToken") + public R refreshToken(@RequestBody RefreshTokenParam param) { + return R.ok(userLoginService.refreshToken(param.getRefreshToken())); + } + + /** + * 密码登录 + */ + @TokenIgnore + @Operation(summary = "密码登录") + @PostMapping("/password") + public R password( + @RequestBody LoginParam param) { + String phone = param.getPhone(); + String password = param.getPassword(); + + CoolPreconditions.checkEmpty(phone); + CoolPreconditions.checkEmpty(password); + return R.ok(userLoginService.password(phone, password)); + } +} diff --git a/src/main/java/com/cool/modules/user/controller/app/params/CaptchaParam.java b/src/main/java/com/cool/modules/user/controller/app/params/CaptchaParam.java new file mode 100644 index 0000000..97e7103 --- /dev/null +++ b/src/main/java/com/cool/modules/user/controller/app/params/CaptchaParam.java @@ -0,0 +1,12 @@ +package com.cool.modules.user.controller.app.params; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class CaptchaParam { + private String type; + private Integer width; + private Integer height; +} diff --git a/src/main/java/com/cool/modules/user/controller/app/params/LoginParam.java b/src/main/java/com/cool/modules/user/controller/app/params/LoginParam.java new file mode 100644 index 0000000..bb4df32 --- /dev/null +++ b/src/main/java/com/cool/modules/user/controller/app/params/LoginParam.java @@ -0,0 +1,34 @@ +package com.cool.modules.user.controller.app.params; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class LoginParam { + + /*******小程序/公众号/微信APP授权 登录*******/ + private String code; + + private String encryptedData; + + private String iv; + + + /*******手机号登录*******/ + private String phone; + + private String smsCode; + + + /*******一键手机号登录*******/ + private String access_token; + + private String openid; + + private String appId; + + + /*******密码登录*******/ + private String password; +} diff --git a/src/main/java/com/cool/modules/user/controller/app/params/RefreshTokenParam.java b/src/main/java/com/cool/modules/user/controller/app/params/RefreshTokenParam.java new file mode 100644 index 0000000..c06065a --- /dev/null +++ b/src/main/java/com/cool/modules/user/controller/app/params/RefreshTokenParam.java @@ -0,0 +1,13 @@ +package com.cool.modules.user.controller.app.params; + +import lombok.Getter; +import lombok.Setter; + +/** + * 刷新token + */ +@Setter +@Getter +public class RefreshTokenParam { + private String refreshToken; +} diff --git a/src/main/java/com/cool/modules/user/controller/app/params/SmsCodeParam.java b/src/main/java/com/cool/modules/user/controller/app/params/SmsCodeParam.java new file mode 100644 index 0000000..c5c8c75 --- /dev/null +++ b/src/main/java/com/cool/modules/user/controller/app/params/SmsCodeParam.java @@ -0,0 +1,12 @@ +package com.cool.modules.user.controller.app.params; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class SmsCodeParam { + private String phone; + private String captchaId; + private String code; +} diff --git a/src/main/java/com/cool/modules/user/entity/UserInfoEntity.java b/src/main/java/com/cool/modules/user/entity/UserInfoEntity.java index 2e778ad..cf6f77c 100644 --- a/src/main/java/com/cool/modules/user/entity/UserInfoEntity.java +++ b/src/main/java/com/cool/modules/user/entity/UserInfoEntity.java @@ -1,10 +1,9 @@ package com.cool.modules.user.entity; import com.cool.core.base.BaseEntity; -import com.tangzc.autotable.annotation.Index; -import com.tangzc.autotable.annotation.enums.IndexTypeEnum; -import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; import com.mybatisflex.annotation.Table; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import com.tangzc.mybatisflex.autotable.annotation.UniIndex; import lombok.Getter; import lombok.Setter; @@ -13,18 +12,18 @@ import lombok.Setter; @Table(value = "user_info", comment = "用户信息") public class UserInfoEntity extends BaseEntity { - @Index(type = IndexTypeEnum.UNIQUE) - @ColumnDefine(comment = "登录唯一ID", notNull = true) + @UniIndex + @ColumnDefine(comment = "登录唯一ID") private String unionid; - @ColumnDefine(comment = "头像", notNull = true) + @ColumnDefine(comment = "头像") private String avatarUrl; - @ColumnDefine(comment = "昵称", notNull = true) + @ColumnDefine(comment = "昵称") private String nickName; - @Index - @ColumnDefine(comment = "手机号", notNull = true) + @UniIndex + @ColumnDefine(comment = "手机号") private String phone; @ColumnDefine(comment = "性别 0-未知 1-男 2-女", defaultValue = "0") @@ -36,6 +35,6 @@ public class UserInfoEntity extends BaseEntity { @ColumnDefine(comment = "登录方式 0-小程序 1-公众号 2-H5", defaultValue = "0") private String loginType; - @ColumnDefine(comment = "密码", notNull = true) + @ColumnDefine(comment = "密码") private String password; } diff --git a/src/main/java/com/cool/modules/user/service/UserInfoService.java b/src/main/java/com/cool/modules/user/service/UserInfoService.java index 4454c6f..bcc2b31 100644 --- a/src/main/java/com/cool/modules/user/service/UserInfoService.java +++ b/src/main/java/com/cool/modules/user/service/UserInfoService.java @@ -9,5 +9,5 @@ public interface UserInfoService extends BaseService { * @param userId * @return */ - Object person(Long userId); + UserInfoEntity person(Long userId); } diff --git a/src/main/java/com/cool/modules/user/service/UserLoginService.java b/src/main/java/com/cool/modules/user/service/UserLoginService.java index a8329b2..9c8048f 100644 --- a/src/main/java/com/cool/modules/user/service/UserLoginService.java +++ b/src/main/java/com/cool/modules/user/service/UserLoginService.java @@ -28,4 +28,30 @@ public interface UserLoginService { * @return 新的token */ Object refreshToken(String refreshToken); + /** + * 小程序登录 + */ + Object mini(String code, String encryptedData, String iv); + /** + * 公众号登录 + */ + Object mp(String code); + /** + * 微信APP授权登录 + */ + Object wxApp(String code); + + /** + * 一键手机号登录 + */ + Object uniPhone(String accessToken, String openid, String appId); + /** + * 绑定小程序手机号 + */ + Object miniPhone(String code, String encryptedData, String iv); + + /** + * 密码登录 + */ + Object password(String phone, String password); } diff --git a/src/main/java/com/cool/modules/user/service/impl/UserInfoServiceImpl.java b/src/main/java/com/cool/modules/user/service/impl/UserInfoServiceImpl.java index 77f5729..52858b5 100644 --- a/src/main/java/com/cool/modules/user/service/impl/UserInfoServiceImpl.java +++ b/src/main/java/com/cool/modules/user/service/impl/UserInfoServiceImpl.java @@ -11,7 +11,7 @@ public class UserInfoServiceImpl extends BaseServiceImpl authority = + List.of(new SimpleGrantedAuthority("ROLE_" + UserTypeEnum.APP.name())); + @Override public void smsCode(String phone, String captchaId, String code) { - + // 校验图片验证码,不通过直接抛异常 + baseSysLoginService.captchaCheck(captchaId, code); + userSmsUtil.sendVerifyCode(phone, SendSceneEnum.login); + coolCache.del("verify:img:" + captchaId); } @Override public Object phoneVerifyCode(String phone, String smsCode) { + // 校验短信验证码,不通过直接抛异常 + userSmsUtil.checkVerifyCode(phone, smsCode, SendSceneEnum.login); + return generateTokenByPhone(phone); + } + + + @Override + public Object refreshToken(String refreshToken) { + CoolPreconditions.check(!jwtTokenUtil.validateRefreshToken(refreshToken), "错误的refreshToken"); + JWT jwt = jwtTokenUtil.getTokenInfo(refreshToken); + CoolPreconditions.check(jwt == null || !(Boolean) jwt.getPayload("isRefresh"), + "错误的refreshToken"); + Long userId = Convert.toLong(jwt.getPayload("userId")); + return generateToken(userId, refreshToken); + } + + @Override + public Object mini(String code, String encryptedData, String iv) { return null; } @Override - public Object refreshToken(String refreshToken) { - JWT jwt = jwtTokenUtil.getTokenInfo(refreshToken); - try { - CoolPreconditions.check(jwt == null || !(Boolean) jwt.getPayload("isRefresh"), - "错误的token"); + public Object mp(String code) { + return null; + } - UserInfoEntity userInfoEntity = - userInfoMapper.selectOneById(Convert.toLong(jwt.getPayload("userId"))); - Dict tokenInfo = - Dict.create() - .set("userId", userInfoEntity.getId()); - String token = jwtTokenUtil.generateToken(tokenInfo); - refreshToken = jwtTokenUtil.generateRefreshToken(tokenInfo); - return Dict.create() - .set("token", token) - .set("expire", jwtTokenUtil.getExpire()) - .set("refreshToken", refreshToken) - .set("refreshExpire", jwtTokenUtil.getRefreshExpire()); - } catch (Exception e) { - throw new CoolException("错误的token", e); + @Override + public Object wxApp(String code) { + return null; + } + + @Override + public Object uniPhone(String accessToken, String openid, String appId) { + return null; + } + + @Override + public Object miniPhone(String code, String encryptedData, String iv) { + return null; + } + + @Override + public Object password(String phone, String password) { + UserInfoEntity userInfoEntity = userInfoMapper.selectOneByQuery( + QueryWrapper.create().eq(UserInfoEntity::getPhone, phone)); + CoolPreconditions.checkEmpty(userInfoEntity, "账号或密码错误"); + if (userInfoEntity.getPassword().equals(MD5.create().digestHex(password))) { + return generateToken(userInfoEntity, null); } + CoolPreconditions.checkEmpty(userInfoEntity, "账号或密码错误"); + return null; + } + + /** + * 前置已校验用户的手机号, + * 根据手机号找到用户生成token + */ + private Object generateTokenByPhone(String phone) { + UserInfoEntity userInfoEntity = userInfoMapper.selectOneByQuery( + QueryWrapper.create().eq(UserInfoEntity::getPhone, phone)); + return generateToken(userInfoEntity, null); + } + + /** + * 生成token + */ + private Dict generateToken(Long userId, String refreshToken) { + UserInfoEntity userInfoEntity = userInfoMapper.selectOneById(userId); + return generateToken(userInfoEntity, refreshToken); + } + private Dict generateToken(UserInfoEntity userInfoEntity, String refreshToken) { + Dict tokenInfo = Dict.create() + .set("userType", UserTypeEnum.APP.name()) + .set("userId", userInfoEntity.getId()); + String token = jwtTokenUtil.generateToken(tokenInfo); + if (ObjUtil.isEmpty(refreshToken)) { + refreshToken = jwtTokenUtil.generateRefreshToken(tokenInfo); + } + JwtUser jwtUser = new JwtUser(userInfoEntity.getId(), + authority, + ObjUtil.equals(userInfoEntity.getStatus(), 1)); + coolCache.set("app:userDetails:" + jwtUser.getUserId(), jwtUser); + return Dict.create() + .set("token", token) + .set("expire", jwtTokenUtil.getExpire()) + .set("refreshToken", refreshToken) + .set("refreshExpire", jwtTokenUtil.getRefreshExpire()); } } diff --git a/src/main/java/com/cool/modules/user/token/UserTokenInterceptor.java b/src/main/java/com/cool/modules/user/token/UserTokenInterceptor.java deleted file mode 100644 index 8183149..0000000 --- a/src/main/java/com/cool/modules/user/token/UserTokenInterceptor.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.cool.modules.user.token; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.jwt.JWT; -import com.cool.core.annotation.TokenIgnore; -import com.cool.core.security.jwt.JwtTokenUtil; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.HandlerInterceptor; - -/** - * 用户Token拦截器 - */ -@Slf4j -@RequiredArgsConstructor -@Component -public class UserTokenInterceptor implements HandlerInterceptor { - - private final JwtTokenUtil jwtTokenUtil; - - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - // 检查是否有 TokenIgnore 注解,有则跳过 - if (handler instanceof HandlerMethod) { - HandlerMethod handlerMethod = (HandlerMethod) handler; - if (handlerMethod.getMethodAnnotation(TokenIgnore.class) != null || - handlerMethod.getBeanType().getAnnotation(TokenIgnore.class) != null) { - return true; - } - } - String token = request.getHeader("Authorization"); - if (StrUtil.isNotEmpty(token)) { - try { - if (jwtTokenUtil.validateToken(token)) { - JWT jwt = jwtTokenUtil.getTokenInfo(token); - String userId = jwt.getPayload("userId").toString(); - request.setAttribute("appUserId", userId); - return true; - } - } catch (Exception e) { - // Logging can be added here if needed - log.error("Invalid Token", e); - } - } - response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - response.getWriter().write("Invalid Token"); - return false; - } -} diff --git a/src/main/java/com/cool/modules/user/token/UserWebConfig.java b/src/main/java/com/cool/modules/user/token/UserWebConfig.java deleted file mode 100644 index 03d32b1..0000000 --- a/src/main/java/com/cool/modules/user/token/UserWebConfig.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.cool.modules.user.token; - -import lombok.RequiredArgsConstructor; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -/** - * 用户Web配置 - */ -@RequiredArgsConstructor -@Configuration -public class UserWebConfig implements WebMvcConfigurer { - final private UserTokenInterceptor userTokenInterceptor; - - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(userTokenInterceptor) - .addPathPatterns("/app/**"); - } -} diff --git a/src/main/java/com/cool/modules/user/util/UserSmsUtil.java b/src/main/java/com/cool/modules/user/util/UserSmsUtil.java index e521de1..6ee80eb 100644 --- a/src/main/java/com/cool/modules/user/util/UserSmsUtil.java +++ b/src/main/java/com/cool/modules/user/util/UserSmsUtil.java @@ -3,16 +3,16 @@ package com.cool.modules.user.util; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import com.cool.core.cache.CoolCache; +import com.cool.core.exception.CoolPreconditions; import com.cool.core.plugin.service.CoolPluginService; import com.cool.core.util.CoolPluginInvokers; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; /** * UserSmsUtil - 用户短信工具类 @@ -23,6 +23,13 @@ import java.util.Map; @Component public class UserSmsUtil { + /** + * 短信发送场景枚举 + */ + public enum SendSceneEnum { + login, // 登录 + } + private final CoolPluginService coolPluginService; private final CoolCache coolCache; @@ -31,13 +38,12 @@ public class UserSmsUtil { * 发送短信验证码 * * @param phone - * @param code */ - void sendVerifyCode(String phone, String code) { + public void sendVerifyCode(String phone, SendSceneEnum sendSceneEnum) { // 随机生成4位验证码 String verifyCode = RandomUtil.randomNumbers(4); send(phone, verifyCode); - coolCache.set("sms:" + phone, verifyCode, 60 * 10); + coolCache.set(sendSceneEnum.name() + "_sms:" + phone, verifyCode, 60 * 10); } /** @@ -46,27 +52,33 @@ public class UserSmsUtil { * @param code * @return */ - boolean checkVerifyCode(String phone, String code) { - String cacheCode = coolCache.get("sms:" + phone, String.class); - return StrUtil.isNotEmpty(code) && code.equals(cacheCode); + public void checkVerifyCode(String phone, String code, SendSceneEnum sendSceneEnum) { + String key = sendSceneEnum.name() + "_sms:" + phone; + String cacheCode = coolCache.get(key, String.class); + boolean flag = StrUtil.isNotEmpty(code) && code.equals(cacheCode); + if (flag) { + // 删除验证码 + coolCache.del(key); + } + CoolPreconditions.check(!flag, "验证码错误"); } - /** * 发送短信 * * @param phone * @param code */ - void send(String phone, String code) { + public void send(String phone, String code) { List phones = new ArrayList<>(); - phones.add("xxx"); + phones.add(phone); Map params = new HashMap<>(); params.put("code", code); // 插件key sms-tx、sms-ali,哪个实例存在就调用哪个 if (coolPluginService.getInstance("sms-tx") != null) { // 调用腾讯短信插件 + CoolPluginInvokers.invoke("sms-tx", "send", phones, params); } else if (coolPluginService.getInstance("sms-ali") != null) { // 调用阿里短信插件 CoolPluginInvokers.invoke("sms-ali", "send", phones, params); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 21fc220..1700b88 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -64,7 +64,7 @@ spring: useProperties: false threadPool: class: org.quartz.simpl.SimpleThreadPool - threadCount: 1000 + threadCount: 5 threadPriority: 9 threadsInheritContextClassLoaderOfInitializingThread: true @@ -77,7 +77,6 @@ ignored: - /actuator/** - /download/** - /static/** - - /app/** - /favicon.ico - /v3/api-docs/** - /swagger @@ -88,6 +87,11 @@ ignored: - /admin/base/open/** # 忽略记录请求日志url logUrls: + - / + - /app/** + - /css/* + - /js/* + - /favicon.ico # 文档 springdoc: api-docs: