diff --git a/src/main/java/com/cool/core/annotation/TokenIgnore.java b/src/main/java/com/cool/core/annotation/TokenIgnore.java new file mode 100644 index 0000000..1392043 --- /dev/null +++ b/src/main/java/com/cool/core/annotation/TokenIgnore.java @@ -0,0 +1,14 @@ +package com.cool.core.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 忽略Token验证 + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface TokenIgnore { +} diff --git a/src/main/java/com/cool/core/base/controller/CommonController.java b/src/main/java/com/cool/core/base/controller/CommonController.java deleted file mode 100644 index b2b74a4..0000000 --- a/src/main/java/com/cool/core/base/controller/CommonController.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.cool.core.base.controller; - -import cn.hutool.core.util.ObjUtil; -import com.cool.core.plugin.service.CoolPluginService; -import com.cool.core.util.ConvertUtil; -import com.cool.core.util.CoolPluginInvokers; -import java.io.File; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.multipart.MultipartFile; - -@Controller -@RequiredArgsConstructor -public class CommonController { - - final private CoolPluginService coolPluginService; - - @RequestMapping("/") - public String welcome() { - return "welcome"; - } - - @PostMapping("/testPlugin/invokeMethod") - @ResponseBody - public String invokeMethod(@RequestParam String key, @RequestParam String methodName) { - Object result = null; - if (ObjUtil.isEmpty(methodName)) { - result = CoolPluginInvokers.invokePlugin(key); - } else { - result = CoolPluginInvokers.invokePlugin(key, methodName); - } - System.out.println(result); - return "invokeMethod Result: " + result; - } - - /** - * 指定目录加载插件 - */ - @PostMapping("/testPlugin/reload") - @ResponseBody - public String reload() { - // 替换掉自己插件编译的路径,无需在页面上上传 - File file = new File( - "/Users/mac/work/cool_new/cool-admin-java-plugin/target/my_cool_plugin.cool"); - MultipartFile multipartFile = ConvertUtil.convertToMultipartFile(file); - coolPluginService.install(multipartFile, true); - return "reload Success"; - } -} diff --git a/src/main/java/com/cool/core/request/prefix/AutoPrefixUrlMapping.java b/src/main/java/com/cool/core/request/prefix/AutoPrefixUrlMapping.java index 2d1b300..a1891f3 100644 --- a/src/main/java/com/cool/core/request/prefix/AutoPrefixUrlMapping.java +++ b/src/main/java/com/cool/core/request/prefix/AutoPrefixUrlMapping.java @@ -97,4 +97,4 @@ public class AutoPrefixUrlMapping extends RequestMappingHandlerMapping { return dotPath; } -} \ No newline at end of file +} diff --git a/src/main/java/com/cool/core/security/JwtSecurityConfig.java b/src/main/java/com/cool/core/security/JwtSecurityConfig.java index b5dbc68..9ccd4c9 100644 --- a/src/main/java/com/cool/core/security/JwtSecurityConfig.java +++ b/src/main/java/com/cool/core/security/JwtSecurityConfig.java @@ -1,5 +1,7 @@ package com.cool.core.security; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.annotation.TokenIgnore; import com.cool.modules.base.security.JwtAuthenticationTokenFilter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -19,6 +21,18 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.util.DigestUtils; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.core.annotation.AnnotatedElementUtils; +import org.springframework.context.ApplicationContext; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; +import org.springframework.web.util.pattern.PathPattern; + +import java.lang.reflect.Method; +import java.util.Map; +import java.util.function.Predicate; @EnableWebSecurity @Configuration @@ -28,7 +42,6 @@ public class JwtSecurityConfig { // 用户详情 final private UserDetailsService userDetailsService; - final private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; // 401 final private EntryPointUnauthorizedHandler entryPointUnauthorizedHandler; @@ -37,23 +50,53 @@ public class JwtSecurityConfig { // 忽略权限控制的地址 final private IgnoredUrlsProperties ignoredUrlsProperties; + final private RequestMappingHandlerMapping requestMappingHandlerMapping; + @Bean - public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception { + public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity, ApplicationContext applicationContext) throws Exception { + // 动态获取忽略的URL + configureIgnoredUrls(); + return httpSecurity - .authorizeHttpRequests( - conf -> conf.requestMatchers( - ignoredUrlsProperties.getUrls().toArray(String[]::new)) - .permitAll().anyRequest().authenticated()) - .headers(config -> config.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable)) - // 允许网页iframe - .csrf(AbstractHttpConfigurer::disable) - .sessionManagement(conf -> conf.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - .addFilterBefore(jwtAuthenticationTokenFilter, - UsernamePasswordAuthenticationFilter.class) - .exceptionHandling(config -> { - config.authenticationEntryPoint(entryPointUnauthorizedHandler); - config.accessDeniedHandler(restAccessDeniedHandler); - }).build(); + .authorizeHttpRequests( + conf -> conf.requestMatchers( + ignoredUrlsProperties.getUrls().toArray(String[]::new)) + .permitAll().anyRequest().authenticated()) + .headers(config -> config.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable)) + // 允许网页iframe + .csrf(AbstractHttpConfigurer::disable) + .sessionManagement(conf -> conf.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .addFilterBefore(jwtAuthenticationTokenFilter, + UsernamePasswordAuthenticationFilter.class) + .exceptionHandling(config -> { + config.authenticationEntryPoint(entryPointUnauthorizedHandler); + config.accessDeniedHandler(restAccessDeniedHandler); + }).build(); + } + + private void configureIgnoredUrls() { + Map mappings = requestMappingHandlerMapping.getHandlerMethods(); + mappings.forEach((requestMappingInfo, handlerMethod) -> { + Method method = handlerMethod.getMethod(); + TokenIgnore tokenIgnore = AnnotatedElementUtils.findMergedAnnotation(method, TokenIgnore.class); + if (tokenIgnore != null) { + StringBuilder url = new StringBuilder(); + RequestMapping classRequestMapping = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(), RequestMapping.class); + if (classRequestMapping != null) { + for (String path : classRequestMapping.value()) { + url.append(path); + } + } + if (requestMappingInfo.getPathPatternsCondition() == null) { + return; + } + // requestMappingInfo.getPathPatternsCondition().getPatterns() + for (PathPattern path : requestMappingInfo.getPathPatternsCondition().getPatterns()) { + url.append(path); + } + ignoredUrlsProperties.getUrls().add(url.toString()); + } + }); } @Bean @@ -67,7 +110,7 @@ public class JwtSecurityConfig { @Override public boolean matches(CharSequence rawPassword, String encodedPassword) { return encodedPassword.equals( - DigestUtils.md5DigestAsHex(((String) rawPassword).getBytes())); + DigestUtils.md5DigestAsHex(((String) rawPassword).getBytes())); } }; } @@ -82,7 +125,7 @@ public class JwtSecurityConfig { @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration config) - throws Exception { + throws Exception { return config.getAuthenticationManager(); } } 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 127b0f7..4e3eec0 100644 --- a/src/main/java/com/cool/core/security/jwt/JwtTokenUtil.java +++ b/src/main/java/com/cool/core/security/jwt/JwtTokenUtil.java @@ -121,4 +121,15 @@ public class JwtTokenUtil implements Serializable { boolean isValidSignature = JWTUtil.verify(token, secret.getBytes()); return (tokenUsername.equals(username) && !isTokenExpired(token) && isValidSignature); } + + /** + * 校验token是否有效 + * @param token + * @return + */ + public Boolean validateToken(String token) { + String secret = getSecret(); + boolean isValidSignature = JWTUtil.verify(token, secret.getBytes()); + return (!isTokenExpired(token) && isValidSignature); + } } 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 0fe42ff..cbfd918 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 @@ -2,6 +2,7 @@ package com.cool.modules.base.controller.admin; import cn.hutool.core.lang.Dict; import com.cool.core.annotation.CoolRestController; +import com.cool.core.annotation.TokenIgnore; import com.cool.core.eps.CoolEps; import com.cool.core.file.FileUploadStrategyFactory; import com.cool.core.request.R; @@ -40,6 +41,7 @@ public class AdminBaseCommController { final private FileUploadStrategyFactory fileUploadStrategyFactory; + @TokenIgnore @Operation(summary = "实体信息与路径", description = "系统所有的实体信息与路径,供前端自动生成代码与服务") @GetMapping("/eps") public R eps() { diff --git a/src/main/java/com/cool/modules/base/controller/app/AppBaseCommController.java b/src/main/java/com/cool/modules/base/controller/app/AppBaseCommController.java index 447207f..af4a017 100644 --- a/src/main/java/com/cool/modules/base/controller/app/AppBaseCommController.java +++ b/src/main/java/com/cool/modules/base/controller/app/AppBaseCommController.java @@ -1,6 +1,7 @@ package com.cool.modules.base.controller.app; import com.cool.core.annotation.CoolRestController; +import com.cool.core.annotation.TokenIgnore; import com.cool.core.eps.CoolEps; import com.cool.core.request.R; import io.swagger.v3.oas.annotations.Operation; @@ -18,6 +19,7 @@ public class AppBaseCommController { final private CoolEps coolEps; + @TokenIgnore @Operation(summary = "实体信息与路径", description = "系统所有的实体信息与路径,供前端自动生成代码与服务") @GetMapping("/eps") public R eps() { diff --git a/src/main/java/com/cool/modules/base/security/JwtAuthenticationTokenFilter.java b/src/main/java/com/cool/modules/base/security/JwtAuthenticationTokenFilter.java index 11b08ca..cddbbd8 100644 --- a/src/main/java/com/cool/modules/base/security/JwtAuthenticationTokenFilter.java +++ b/src/main/java/com/cool/modules/base/security/JwtAuthenticationTokenFilter.java @@ -3,6 +3,7 @@ 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; @@ -10,8 +11,10 @@ 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; @@ -20,6 +23,9 @@ 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过滤器 @@ -31,28 +37,46 @@ 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 { + 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) { + && SecurityContextHolder.getContext().getAuthentication() == null) { UserDetails userDetails = coolCache.get("admin:userDetails:" + username, - JwtUser.class); + JwtUser.class); Integer passwordV = Convert.toInt(jwt.getPayload("passwordVersion")); Integer rv = coolCache.get("admin:passwordVersion:" + jwt.getPayload("userId"), - Integer.class); + Integer.class); if (jwtTokenUtil.validateToken(authToken, username) && Objects.equals(passwordV, rv) - && userDetails != null) { + && userDetails != null) { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( - userDetails, null, userDetails.getAuthorities()); + userDetails, null, userDetails.getAuthorities()); authentication.setDetails( - new WebAuthenticationDetailsSource().buildDetails(request)); + new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authentication); request.setAttribute("adminUsername", jwt.getPayload("username")); request.setAttribute("adminUserId", jwt.getPayload("userId")); 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 new file mode 100644 index 0000000..0be0fe3 --- /dev/null +++ b/src/main/java/com/cool/modules/user/controller/app/AppUserInfoController.java @@ -0,0 +1,23 @@ +package com.cool.modules.user.controller.app; + +import com.cool.core.annotation.CoolRestController; +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() +public class AppUserInfoController { + + private final UserInfoService userInfoService; + + @Operation(summary = "用户个人信息", description = "获得App、小程序或者其他应用的用户个人信息") + @GetMapping("/person") + public Object person(@RequestAttribute("appUserId") Long appUserId) { + return userInfoService.person(appUserId); + } +} 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 bf5e41d..4454c6f 100644 --- a/src/main/java/com/cool/modules/user/service/UserInfoService.java +++ b/src/main/java/com/cool/modules/user/service/UserInfoService.java @@ -4,4 +4,10 @@ import com.cool.core.base.BaseService; import com.cool.modules.user.entity.UserInfoEntity; public interface UserInfoService extends BaseService { + /** + * 用户个人信息 + * @param userId + * @return + */ + Object 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 new file mode 100644 index 0000000..a8329b2 --- /dev/null +++ b/src/main/java/com/cool/modules/user/service/UserLoginService.java @@ -0,0 +1,31 @@ +package com.cool.modules.user.service; + +/** + * 用户登录 + */ +public interface UserLoginService { + + /** + * 发送短信验证码 + * @param phone + * @param captchaId + * @param code + */ + void smsCode(String phone, String captchaId, String code); + + /** + * 手机号验证码登录 + * @param phone + * @param smsCode + */ + Object phoneVerifyCode(String phone, String smsCode); + + + /** + * 刷新token + * + * @param refreshToken 刷新token + * @return 新的token + */ + Object refreshToken(String refreshToken); +} 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 0835aad..77f5729 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 @@ -10,4 +10,10 @@ import org.springframework.stereotype.Service; public class UserInfoServiceImpl extends BaseServiceImpl implements UserInfoService { + @Override + public Object person(Long userId) { + UserInfoEntity info = mapper.selectOneById(userId); + info.setPassword(null); + return info; + } } diff --git a/src/main/java/com/cool/modules/user/service/impl/UserLoginServiceImpl.java b/src/main/java/com/cool/modules/user/service/impl/UserLoginServiceImpl.java new file mode 100644 index 0000000..8eccd57 --- /dev/null +++ b/src/main/java/com/cool/modules/user/service/impl/UserLoginServiceImpl.java @@ -0,0 +1,65 @@ +package com.cool.modules.user.service.impl; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.Dict; +import cn.hutool.jwt.JWT; +import com.cool.core.cache.CoolCache; +import com.cool.core.exception.CoolException; +import com.cool.core.exception.CoolPreconditions; +import com.cool.core.security.jwt.JwtTokenUtil; +import com.cool.modules.base.security.CoolSecurityUtil; +import com.cool.modules.user.entity.UserInfoEntity; +import com.cool.modules.user.mapper.UserInfoMapper; +import com.cool.modules.user.service.UserLoginService; +import lombok.RequiredArgsConstructor; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class UserLoginServiceImpl implements UserLoginService { + + private final CoolCache coolCache; + + private final AuthenticationManager authenticationManager; + + private final CoolSecurityUtil coolSecurityUtil; + + private final JwtTokenUtil jwtTokenUtil; + + private final UserInfoMapper userInfoMapper; + + @Override + public void smsCode(String phone, String captchaId, String code) { + + } + + @Override + public Object phoneVerifyCode(String phone, String smsCode) { + return null; + } + + @Override + public Object refreshToken(String refreshToken) { + JWT jwt = jwtTokenUtil.getTokenInfo(refreshToken); + try { + CoolPreconditions.check(jwt == null || !(Boolean) jwt.getPayload("isRefresh"), + "错误的token"); + + 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); + } + } +} diff --git a/src/main/java/com/cool/modules/user/token/UserTokenInterceptor.java b/src/main/java/com/cool/modules/user/token/UserTokenInterceptor.java new file mode 100644 index 0000000..8183149 --- /dev/null +++ b/src/main/java/com/cool/modules/user/token/UserTokenInterceptor.java @@ -0,0 +1,53 @@ +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 new file mode 100644 index 0000000..03d32b1 --- /dev/null +++ b/src/main/java/com/cool/modules/user/token/UserWebConfig.java @@ -0,0 +1,21 @@ +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 new file mode 100644 index 0000000..e521de1 --- /dev/null +++ b/src/main/java/com/cool/modules/user/util/UserSmsUtil.java @@ -0,0 +1,78 @@ +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.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; + +/** + * UserSmsUtil - 用户短信工具类 + * 该类用于发送短信验证码。 + */ +@RequiredArgsConstructor +@Slf4j +@Component +public class UserSmsUtil { + + private final CoolPluginService coolPluginService; + + private final CoolCache coolCache; + + /** + * 发送短信验证码 + * + * @param phone + * @param code + */ + void sendVerifyCode(String phone, String code) { + // 随机生成4位验证码 + String verifyCode = RandomUtil.randomNumbers(4); + send(phone, verifyCode); + coolCache.set("sms:" + phone, verifyCode, 60 * 10); + } + + /** + * 检查验证码 + * @param phone + * @param code + * @return + */ + boolean checkVerifyCode(String phone, String code) { + String cacheCode = coolCache.get("sms:" + phone, String.class); + return StrUtil.isNotEmpty(code) && code.equals(cacheCode); + } + + + /** + * 发送短信 + * + * @param phone + * @param code + */ + void send(String phone, String code) { + List phones = new ArrayList<>(); + phones.add("xxx"); + + Map params = new HashMap<>(); + params.put("code", code); + // 插件key sms-tx、sms-ali,哪个实例存在就调用哪个 + if (coolPluginService.getInstance("sms-tx") != null) { + // 调用腾讯短信插件 + } else if (coolPluginService.getInstance("sms-ali") != null) { + // 调用阿里短信插件 + CoolPluginInvokers.invoke("sms-ali", "send", phones, params); + } else { + // 未找到短信插件 + log.error("未找到短信插件,请前往插件市场下载安装"); + } + } +} diff --git a/src/main/java/com/cool/modules/user/util/UserWxUtil.java b/src/main/java/com/cool/modules/user/util/UserWxUtil.java new file mode 100644 index 0000000..74b32eb --- /dev/null +++ b/src/main/java/com/cool/modules/user/util/UserWxUtil.java @@ -0,0 +1,12 @@ +package com.cool.modules.user.util; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +/** + * UserWxUtil - 用户微信工具类 + */ +@Component +@RequiredArgsConstructor +public class UserWxUtil { +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 82e4842..ef0ec9b 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -85,8 +85,7 @@ ignored: - /js/* - /druid/** - /admin/base/open/** - - /admin/base/comm/eps - - /testPlugin/** + # 文档 springdoc: api-docs: