diff --git a/src/main/java/com/youlai/system/common/util/SecurityUtils.java b/src/main/java/com/youlai/system/common/util/SecurityUtils.java
index 9a64a377..48a7631f 100644
--- a/src/main/java/com/youlai/system/common/util/SecurityUtils.java
+++ b/src/main/java/com/youlai/system/common/util/SecurityUtils.java
@@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.youlai.system.common.constant.SystemConstants;
-import com.youlai.system.base.security.model.SysUserDetails;
+import com.youlai.system.core.security.model.SysUserDetails;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
diff --git a/src/main/java/com/youlai/system/base/mybatisplus/config/MybatisPlusConfig.java b/src/main/java/com/youlai/system/config/MybatisConfig.java
similarity index 86%
rename from src/main/java/com/youlai/system/base/mybatisplus/config/MybatisPlusConfig.java
rename to src/main/java/com/youlai/system/config/MybatisConfig.java
index 018d9ef0..74274c85 100644
--- a/src/main/java/com/youlai/system/base/mybatisplus/config/MybatisPlusConfig.java
+++ b/src/main/java/com/youlai/system/config/MybatisConfig.java
@@ -1,12 +1,12 @@
-package com.youlai.system.base.mybatisplus.config;
+package com.youlai.system.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
-import com.youlai.system.base.mybatisplus.handler.MyDataPermissionHandler;
-import com.youlai.system.base.mybatisplus.handler.MyMetaObjectHandler;
+import com.youlai.system.core.mybatis.handler.MyDataPermissionHandler;
+import com.youlai.system.core.mybatis.handler.MyMetaObjectHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@@ -19,7 +19,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
*/
@Configuration
@EnableTransactionManagement
-public class MybatisPlusConfig {
+public class MybatisConfig {
/**
* 分页插件和数据权限插件
diff --git a/src/main/java/com/youlai/system/base/security/config/SecurityConfig.java b/src/main/java/com/youlai/system/config/SecurityConfig.java
similarity index 93%
rename from src/main/java/com/youlai/system/base/security/config/SecurityConfig.java
rename to src/main/java/com/youlai/system/config/SecurityConfig.java
index f970e35c..01896f04 100644
--- a/src/main/java/com/youlai/system/base/security/config/SecurityConfig.java
+++ b/src/main/java/com/youlai/system/config/SecurityConfig.java
@@ -1,11 +1,11 @@
-package com.youlai.system.base.security.config;
+package com.youlai.system.config;
import com.youlai.system.common.constant.SecurityConstants;
-import com.youlai.system.base.security.exception.MyAccessDeniedHandler;
-import com.youlai.system.base.security.exception.MyAuthenticationEntryPoint;
-import com.youlai.system.base.security.jwt.JwtTokenFilter;
+import com.youlai.system.core.security.exception.MyAccessDeniedHandler;
+import com.youlai.system.core.security.exception.MyAuthenticationEntryPoint;
+import com.youlai.system.core.security.jwt.JwtTokenFilter;
import com.youlai.system.filter.VerifyCodeFilter;
-import com.youlai.system.base.security.jwt.JwtTokenProvider;
+import com.youlai.system.core.security.jwt.JwtTokenProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/src/main/java/com/youlai/system/config/WebSocketConfig.java b/src/main/java/com/youlai/system/config/WebSocketConfig.java
new file mode 100644
index 00000000..c44e0fe3
--- /dev/null
+++ b/src/main/java/com/youlai/system/config/WebSocketConfig.java
@@ -0,0 +1,111 @@
+package com.youlai.system.config;
+
+import cn.hutool.core.util.StrUtil;
+import com.youlai.system.core.security.jwt.JwtTokenProvider;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpHeaders;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageChannel;
+import org.springframework.messaging.simp.config.ChannelRegistration;
+import org.springframework.messaging.simp.config.MessageBrokerRegistry;
+import org.springframework.messaging.simp.stomp.StompCommand;
+import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
+import org.springframework.messaging.support.ChannelInterceptor;
+import org.springframework.messaging.support.MessageHeaderAccessor;
+import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
+import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
+import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
+
+/**
+ * WebSocket 配置
+ *
+ * @author haoxr
+ * @since 2.4.0
+ */
+@Configuration
+@EnableWebSocketMessageBroker // 启用WebSocket消息代理功能和配置STOMP协议,实现实时双向通信和消息传递
+@RequiredArgsConstructor
+@Slf4j
+public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
+
+ private final JwtTokenProvider jwtTokenProvider;
+
+ /**
+ * 注册一个端点,客户端通过这个端点进行连接
+ */
+ @Override
+ public void registerStompEndpoints(StompEndpointRegistry registry) {
+ registry
+ .addEndpoint("/ws") // 注册了一个 /ws 的端点
+ .setAllowedOriginPatterns("*") // 允许跨域的 WebSocket 连接
+ .withSockJS(); // 启用 SockJS (浏览器不支持WebSocket,SockJS 将会提供兼容性支持)
+ registry.addEndpoint("/ws-app").setAllowedOriginPatterns("*"); // 注册了一个 /ws-app 的端点,支持 uni-app 的 ws 连接协议
+ }
+
+
+ /**
+ * 配置消息代理
+ */
+ @Override
+ public void configureMessageBroker(MessageBrokerRegistry registry) {
+ // 客户端发送消息的请求前缀
+ registry.setApplicationDestinationPrefixes("/app");
+
+ // 客户端订阅消息的请求前缀,topic一般用于广播推送,queue用于点对点推送
+ registry.enableSimpleBroker("/topic", "/queue");
+
+ // 服务端通知客户端的前缀,可以不设置,默认为user
+ registry.setUserDestinationPrefix("/user");
+ }
+
+
+ /**
+ * 配置客户端入站通道拦截器
+ *
+ * @param registration 通道注册器
+ */
+ @Override
+ public void configureClientInboundChannel(ChannelRegistration registration) {
+ registration.interceptors(new ChannelInterceptor() {
+ @Override
+ public Message> preSend(Message> message, MessageChannel channel) {
+ StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
+
+ // 如果 StompHeaderAccessor 为 null,说明不是 STOMP 消息,直接放行
+ if (accessor == null) {
+ return ChannelInterceptor.super.preSend(message, channel);
+ }
+
+ // 如果是连接请求(CONNECT 命令),从请求头中取出 token 并设置到认证信息中
+ if (StompCommand.CONNECT.equals(accessor.getCommand())) {
+ // 从连接头中提取授权令牌
+ String bearerToken = accessor.getFirstNativeHeader(HttpHeaders.AUTHORIZATION);
+
+ // 验证令牌格式并提取用户信息
+ if (StrUtil.isNotBlank(bearerToken) && bearerToken.startsWith("Bearer ")) {
+ try {
+ // 移除 "Bearer " 前缀
+ String tokenWithoutPrefix = bearerToken.substring(7);
+ String username = jwtTokenProvider.getUsername(tokenWithoutPrefix);
+
+ // 如果用户名有效,设置用户到访问器中
+ if (StrUtil.isNotBlank(username)) {
+ accessor.setUser(() -> username);
+ return message;
+ }
+ } catch (Exception e) {
+ // 异常处理,可能是解析令牌失败
+ log.error("Failed to process authentication token.", e);
+ }
+ }
+ }
+
+ // 如果不是连接命令或授权失败,继续执行默认逻辑
+ return ChannelInterceptor.super.preSend(message, channel);
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/com/youlai/system/plugin/xxljob/XxlJobConfig.java b/src/main/java/com/youlai/system/config/XxlJobConfig.java
similarity index 97%
rename from src/main/java/com/youlai/system/plugin/xxljob/XxlJobConfig.java
rename to src/main/java/com/youlai/system/config/XxlJobConfig.java
index d326dd6e..a0f802ed 100644
--- a/src/main/java/com/youlai/system/plugin/xxljob/XxlJobConfig.java
+++ b/src/main/java/com/youlai/system/config/XxlJobConfig.java
@@ -1,4 +1,4 @@
-package com.youlai.system.plugin.xxljob;
+package com.youlai.system.config;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/youlai/system/controller/WebsocketController.java b/src/main/java/com/youlai/system/controller/WebsocketController.java
index 18d724cb..ed82a66e 100644
--- a/src/main/java/com/youlai/system/controller/WebsocketController.java
+++ b/src/main/java/com/youlai/system/controller/WebsocketController.java
@@ -1,6 +1,6 @@
package com.youlai.system.controller;
-import com.youlai.system.model.dto.SocketMessage;
+import com.youlai.system.model.dto.ChatMessage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.handler.annotation.DestinationVariable;
@@ -48,11 +48,14 @@ public class WebsocketController {
* @param message 消息内容
*/
@MessageMapping("/sendToUser/{username}")
- //@SendToUser(value = "/queue/greeting")
public void sendToUser(Principal principal, @DestinationVariable String username, String message) {
- log.info("sender:{};receiver:{}", principal.getName(), username);
- messagingTemplate.convertAndSendToUser(username, "/queue/greeting", new SocketMessage(principal.getName(), message));
- /// return "Hello, " + message;
+
+ String sender = principal.getName(); // 发送人
+ String receiver = username; // 接收人
+
+ log.info("发送人:{}; 接收人:{}", sender, receiver);
+ // 发送消息给指定用户 /user/{username}/queue/greeting
+ messagingTemplate.convertAndSendToUser(receiver, "/queue/greeting", new ChatMessage(sender, message));
}
}
diff --git a/src/main/java/com/youlai/system/base/mybatisplus/annotation/DataPermission.java b/src/main/java/com/youlai/system/core/mybatis/annotation/DataPermission.java
similarity index 90%
rename from src/main/java/com/youlai/system/base/mybatisplus/annotation/DataPermission.java
rename to src/main/java/com/youlai/system/core/mybatis/annotation/DataPermission.java
index edd372a9..63e73277 100644
--- a/src/main/java/com/youlai/system/base/mybatisplus/annotation/DataPermission.java
+++ b/src/main/java/com/youlai/system/core/mybatis/annotation/DataPermission.java
@@ -1,4 +1,4 @@
-package com.youlai.system.base.mybatisplus.annotation;
+package com.youlai.system.core.mybatis.annotation;
import java.lang.annotation.*;
diff --git a/src/main/java/com/youlai/system/base/mybatisplus/handler/MyDataPermissionHandler.java b/src/main/java/com/youlai/system/core/mybatis/handler/MyDataPermissionHandler.java
similarity index 96%
rename from src/main/java/com/youlai/system/base/mybatisplus/handler/MyDataPermissionHandler.java
rename to src/main/java/com/youlai/system/core/mybatis/handler/MyDataPermissionHandler.java
index 82a275a8..b39f9b10 100644
--- a/src/main/java/com/youlai/system/base/mybatisplus/handler/MyDataPermissionHandler.java
+++ b/src/main/java/com/youlai/system/core/mybatis/handler/MyDataPermissionHandler.java
@@ -1,9 +1,9 @@
-package com.youlai.system.base.mybatisplus.handler;
+package com.youlai.system.core.mybatis.handler;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
-import com.youlai.system.base.mybatisplus.annotation.DataPermission;
+import com.youlai.system.core.mybatis.annotation.DataPermission;
import com.youlai.system.common.base.IBaseEnum;
import com.youlai.system.common.enums.DataScopeEnum;
import com.youlai.system.common.util.SecurityUtils;
diff --git a/src/main/java/com/youlai/system/base/mybatisplus/handler/MyMetaObjectHandler.java b/src/main/java/com/youlai/system/core/mybatis/handler/MyMetaObjectHandler.java
similarity index 94%
rename from src/main/java/com/youlai/system/base/mybatisplus/handler/MyMetaObjectHandler.java
rename to src/main/java/com/youlai/system/core/mybatis/handler/MyMetaObjectHandler.java
index 68bcfc40..9cf7d3d5 100644
--- a/src/main/java/com/youlai/system/base/mybatisplus/handler/MyMetaObjectHandler.java
+++ b/src/main/java/com/youlai/system/core/mybatis/handler/MyMetaObjectHandler.java
@@ -1,4 +1,4 @@
-package com.youlai.system.base.mybatisplus.handler;
+package com.youlai.system.core.mybatis.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
diff --git a/src/main/java/com/youlai/system/base/security/exception/MyAccessDeniedHandler.java b/src/main/java/com/youlai/system/core/security/exception/MyAccessDeniedHandler.java
similarity index 94%
rename from src/main/java/com/youlai/system/base/security/exception/MyAccessDeniedHandler.java
rename to src/main/java/com/youlai/system/core/security/exception/MyAccessDeniedHandler.java
index 60bb2623..c7979301 100644
--- a/src/main/java/com/youlai/system/base/security/exception/MyAccessDeniedHandler.java
+++ b/src/main/java/com/youlai/system/core/security/exception/MyAccessDeniedHandler.java
@@ -1,4 +1,4 @@
-package com.youlai.system.base.security.exception;
+package com.youlai.system.core.security.exception;
import com.youlai.system.common.result.ResultCode;
import com.youlai.system.common.util.ResponseUtils;
diff --git a/src/main/java/com/youlai/system/base/security/exception/MyAuthenticationEntryPoint.java b/src/main/java/com/youlai/system/core/security/exception/MyAuthenticationEntryPoint.java
similarity index 95%
rename from src/main/java/com/youlai/system/base/security/exception/MyAuthenticationEntryPoint.java
rename to src/main/java/com/youlai/system/core/security/exception/MyAuthenticationEntryPoint.java
index a5fd840c..2a82ab8a 100644
--- a/src/main/java/com/youlai/system/base/security/exception/MyAuthenticationEntryPoint.java
+++ b/src/main/java/com/youlai/system/core/security/exception/MyAuthenticationEntryPoint.java
@@ -1,4 +1,4 @@
-package com.youlai.system.base.security.exception;
+package com.youlai.system.core.security.exception;
import com.youlai.system.common.result.ResultCode;
import com.youlai.system.common.util.ResponseUtils;
diff --git a/src/main/java/com/youlai/system/base/security/jwt/JwtTokenFilter.java b/src/main/java/com/youlai/system/core/security/jwt/JwtTokenFilter.java
similarity index 97%
rename from src/main/java/com/youlai/system/base/security/jwt/JwtTokenFilter.java
rename to src/main/java/com/youlai/system/core/security/jwt/JwtTokenFilter.java
index a116f1d7..5fba6042 100644
--- a/src/main/java/com/youlai/system/base/security/jwt/JwtTokenFilter.java
+++ b/src/main/java/com/youlai/system/core/security/jwt/JwtTokenFilter.java
@@ -1,4 +1,4 @@
-package com.youlai.system.base.security.jwt;
+package com.youlai.system.core.security.jwt;
import com.youlai.system.common.result.ResultCode;
import com.youlai.system.common.util.ResponseUtils;
diff --git a/src/main/java/com/youlai/system/base/security/jwt/JwtTokenProvider.java b/src/main/java/com/youlai/system/core/security/jwt/JwtTokenProvider.java
similarity index 98%
rename from src/main/java/com/youlai/system/base/security/jwt/JwtTokenProvider.java
rename to src/main/java/com/youlai/system/core/security/jwt/JwtTokenProvider.java
index 26725297..2f34d6c3 100644
--- a/src/main/java/com/youlai/system/base/security/jwt/JwtTokenProvider.java
+++ b/src/main/java/com/youlai/system/core/security/jwt/JwtTokenProvider.java
@@ -1,8 +1,8 @@
-package com.youlai.system.base.security.jwt;
+package com.youlai.system.core.security.jwt;
import cn.hutool.core.convert.Convert;
import com.youlai.system.common.constant.JwtClaimConstants;
-import com.youlai.system.base.security.model.SysUserDetails;
+import com.youlai.system.core.security.model.SysUserDetails;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
diff --git a/src/main/java/com/youlai/system/base/security/model/SysUserDetails.java b/src/main/java/com/youlai/system/core/security/model/SysUserDetails.java
similarity index 98%
rename from src/main/java/com/youlai/system/base/security/model/SysUserDetails.java
rename to src/main/java/com/youlai/system/core/security/model/SysUserDetails.java
index 124c60e2..578d3a2a 100644
--- a/src/main/java/com/youlai/system/base/security/model/SysUserDetails.java
+++ b/src/main/java/com/youlai/system/core/security/model/SysUserDetails.java
@@ -1,4 +1,4 @@
-package com.youlai.system.base.security.model;
+package com.youlai.system.core.security.model;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
diff --git a/src/main/java/com/youlai/system/base/security/service/PermissionService.java b/src/main/java/com/youlai/system/core/security/service/PermissionService.java
similarity index 98%
rename from src/main/java/com/youlai/system/base/security/service/PermissionService.java
rename to src/main/java/com/youlai/system/core/security/service/PermissionService.java
index ced6e3e8..b13b8784 100644
--- a/src/main/java/com/youlai/system/base/security/service/PermissionService.java
+++ b/src/main/java/com/youlai/system/core/security/service/PermissionService.java
@@ -1,4 +1,4 @@
-package com.youlai.system.base.security.service;
+package com.youlai.system.core.security.service;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
diff --git a/src/main/java/com/youlai/system/base/security/service/SysUserDetailsService.java b/src/main/java/com/youlai/system/core/security/service/SysUserDetailsService.java
similarity index 89%
rename from src/main/java/com/youlai/system/base/security/service/SysUserDetailsService.java
rename to src/main/java/com/youlai/system/core/security/service/SysUserDetailsService.java
index 7d575451..f2f8b26f 100644
--- a/src/main/java/com/youlai/system/base/security/service/SysUserDetailsService.java
+++ b/src/main/java/com/youlai/system/core/security/service/SysUserDetailsService.java
@@ -1,6 +1,6 @@
-package com.youlai.system.base.security.service;
+package com.youlai.system.core.security.service;
-import com.youlai.system.base.security.model.SysUserDetails;
+import com.youlai.system.core.security.model.SysUserDetails;
import com.youlai.system.model.dto.UserAuthInfo;
import com.youlai.system.service.SysUserService;
import lombok.RequiredArgsConstructor;
diff --git a/src/main/java/com/youlai/system/mapper/SysDeptMapper.java b/src/main/java/com/youlai/system/mapper/SysDeptMapper.java
index 73bf622d..3b4aaa97 100644
--- a/src/main/java/com/youlai/system/mapper/SysDeptMapper.java
+++ b/src/main/java/com/youlai/system/mapper/SysDeptMapper.java
@@ -3,7 +3,7 @@ package com.youlai.system.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
-import com.youlai.system.base.mybatisplus.annotation.DataPermission;
+import com.youlai.system.core.mybatis.annotation.DataPermission;
import com.youlai.system.model.entity.SysDept;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
diff --git a/src/main/java/com/youlai/system/mapper/SysUserMapper.java b/src/main/java/com/youlai/system/mapper/SysUserMapper.java
index ebb59ca2..45ffca7e 100644
--- a/src/main/java/com/youlai/system/mapper/SysUserMapper.java
+++ b/src/main/java/com/youlai/system/mapper/SysUserMapper.java
@@ -2,7 +2,7 @@ package com.youlai.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.youlai.system.base.mybatisplus.annotation.DataPermission;
+import com.youlai.system.core.mybatis.annotation.DataPermission;
import com.youlai.system.model.bo.UserBO;
import com.youlai.system.model.entity.SysUser;
import com.youlai.system.model.dto.UserAuthInfo;
diff --git a/src/main/java/com/youlai/system/model/dto/SocketMessage.java b/src/main/java/com/youlai/system/model/dto/ChatMessage.java
similarity index 91%
rename from src/main/java/com/youlai/system/model/dto/SocketMessage.java
rename to src/main/java/com/youlai/system/model/dto/ChatMessage.java
index cda51641..6dd6de32 100644
--- a/src/main/java/com/youlai/system/model/dto/SocketMessage.java
+++ b/src/main/java/com/youlai/system/model/dto/ChatMessage.java
@@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
-public class SocketMessage {
+public class ChatMessage {
/**
* 发送者
diff --git a/src/main/java/com/youlai/system/plugin/dupsubmit/aspect/DuplicateSubmitAspect.java b/src/main/java/com/youlai/system/plugin/dupsubmit/aspect/DuplicateSubmitAspect.java
index 90a08fd6..23777e92 100644
--- a/src/main/java/com/youlai/system/plugin/dupsubmit/aspect/DuplicateSubmitAspect.java
+++ b/src/main/java/com/youlai/system/plugin/dupsubmit/aspect/DuplicateSubmitAspect.java
@@ -4,7 +4,7 @@ import cn.hutool.core.util.StrUtil;
import com.youlai.system.plugin.dupsubmit.annotation.PreventDuplicateSubmit;
import com.youlai.system.common.result.ResultCode;
import com.youlai.system.common.exception.BusinessException;
-import com.youlai.system.base.security.jwt.JwtTokenProvider;
+import com.youlai.system.core.security.jwt.JwtTokenProvider;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/youlai/system/plugin/websocket/WebSocketConfig.java b/src/main/java/com/youlai/system/plugin/websocket/WebSocketConfig.java
deleted file mode 100644
index 85f865c8..00000000
--- a/src/main/java/com/youlai/system/plugin/websocket/WebSocketConfig.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.youlai.system.plugin.websocket;
-
-import lombok.RequiredArgsConstructor;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.messaging.simp.config.ChannelRegistration;
-import org.springframework.messaging.simp.config.MessageBrokerRegistry;
-import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
-import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
-import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
-
-/**
- * WebSocket 配置
- *
- * @author haoxr
- * @since 2.4.0
- */
-@Configuration
-@EnableWebSocketMessageBroker // 启用WebSocket消息代理功能和配置STOMP协议,实现实时双向通信和消息传递
-@RequiredArgsConstructor
-public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
-
- private final WebsocketChannelInterceptor websocketChannelInterceptor;
-
- /**
- * 注册一个端点,客户端通过这个端点进行连接
- */
- @Override
- public void registerStompEndpoints(StompEndpointRegistry registry) {
- registry
- .addEndpoint("/ws") // 注册了一个 /ws 的端点
- .setAllowedOriginPatterns("*") // 允许跨域的 WebSocket 连接
- .withSockJS(); // 启用 SockJS (浏览器不支持WebSocket,SockJS 将会提供兼容性支持)
- registry.addEndpoint("/ws-app").setAllowedOriginPatterns("*"); // 注册了一个 /ws-app 的端点,支持 uni-app 的 ws 连接协议
- }
-
-
- /**
- * 配置消息代理
- */
- @Override
- public void configureMessageBroker(MessageBrokerRegistry registry) {
- // 客户端发送消息的请求前缀
- registry.setApplicationDestinationPrefixes("/app");
-
- // 客户端订阅消息的请求前缀,topic一般用于广播推送,queue用于点对点推送
- registry.enableSimpleBroker("/topic", "/queue");
-
- // 服务端通知客户端的前缀,可以不设置,默认为user
- registry.setUserDestinationPrefix("/user");
- }
-
-
- /**
- * 配置客户端入站通道拦截器
- *
- * @param registration 通道注册器
- */
- @Override
- public void configureClientInboundChannel(ChannelRegistration registration) {
- registration.interceptors(websocketChannelInterceptor);
- }
-}
diff --git a/src/main/java/com/youlai/system/plugin/websocket/WebsocketChannelInterceptor.java b/src/main/java/com/youlai/system/plugin/websocket/WebsocketChannelInterceptor.java
deleted file mode 100644
index bbfca0f2..00000000
--- a/src/main/java/com/youlai/system/plugin/websocket/WebsocketChannelInterceptor.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.youlai.system.plugin.websocket;
-
-import cn.hutool.core.util.StrUtil;
-import com.youlai.system.base.security.jwt.JwtTokenProvider;
-import lombok.RequiredArgsConstructor;
-import org.springframework.messaging.Message;
-import org.springframework.messaging.MessageChannel;
-import org.springframework.messaging.simp.stomp.StompCommand;
-import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
-import org.springframework.messaging.support.ChannelInterceptor;
-import org.springframework.messaging.support.MessageHeaderAccessor;
-import org.springframework.stereotype.Component;
-
-import java.security.Principal;
-
-/**
- * Websocket 连接认证拦截器
- *
- * @author haoxr
- * @since 2.4.0
- */
-@Component
-@RequiredArgsConstructor
-public class WebsocketChannelInterceptor implements ChannelInterceptor {
-
- private final JwtTokenProvider jwtTokenProvider;
-
- /**
- * 连接前监听
- *
- * @param message 消息
- * @param channel 通道
- * @return
- */
- @Override
- public Message> preSend(Message> message, MessageChannel channel) {
- StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
- assert accessor != null;
-
- if (StompCommand.CONNECT.equals(accessor.getCommand())) {
- String bearerToken = accessor.getFirstNativeHeader("Authorization");
- if (StrUtil.isNotBlank(bearerToken)) {
- bearerToken = bearerToken.substring(7); // remove "Bearer "
- String username = jwtTokenProvider.getUsername(bearerToken);
- if (StrUtil.isNotBlank(username)) {
- Principal principal = () -> username;
- accessor.setUser(principal);
- return message;
- }
- }
- }
- return ChannelInterceptor.super.preSend(message, channel);
- }
-
-}
diff --git a/src/main/java/com/youlai/system/service/impl/AuthServiceImpl.java b/src/main/java/com/youlai/system/service/impl/AuthServiceImpl.java
index fedac225..a34e4ed5 100644
--- a/src/main/java/com/youlai/system/service/impl/AuthServiceImpl.java
+++ b/src/main/java/com/youlai/system/service/impl/AuthServiceImpl.java
@@ -1,10 +1,9 @@
package com.youlai.system.service.impl;
-import cn.hutool.captcha.AbstractCaptcha;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.youlai.system.common.constant.CacheConstants;
-import com.youlai.system.base.security.jwt.JwtTokenProvider;
+import com.youlai.system.core.security.jwt.JwtTokenProvider;
import com.youlai.system.model.dto.CaptchaResult;
import com.youlai.system.model.dto.LoginResult;
import com.youlai.system.plugin.captcha.CaptchaGenerator;
diff --git a/src/main/java/com/youlai/system/service/impl/SysRoleServiceImpl.java b/src/main/java/com/youlai/system/service/impl/SysRoleServiceImpl.java
index 7561592d..4771cbba 100644
--- a/src/main/java/com/youlai/system/service/impl/SysRoleServiceImpl.java
+++ b/src/main/java/com/youlai/system/service/impl/SysRoleServiceImpl.java
@@ -10,7 +10,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.system.common.constant.SystemConstants;
import com.youlai.system.common.model.Option;
import com.youlai.system.converter.RoleConverter;
-import com.youlai.system.base.security.service.PermissionService;
+import com.youlai.system.core.security.service.PermissionService;
import com.youlai.system.mapper.SysRoleMapper;
import com.youlai.system.model.entity.SysRole;
import com.youlai.system.model.entity.SysRoleMenu;
From 974f32b268872d234ad14a03ef72899b386ad4c0 Mon Sep 17 00:00:00 2001
From: haoxr <1490493387@qq.com>
Date: Thu, 14 Dec 2023 23:36:41 +0800
Subject: [PATCH 2/4] =?UTF-8?q?refactor:=20websocket=20=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../youlai/system/config/WebSocketConfig.java | 17 +++++------------
.../system/controller/WebsocketController.java | 2 +-
2 files changed, 6 insertions(+), 13 deletions(-)
diff --git a/src/main/java/com/youlai/system/config/WebSocketConfig.java b/src/main/java/com/youlai/system/config/WebSocketConfig.java
index c44e0fe3..9ef3eccc 100644
--- a/src/main/java/com/youlai/system/config/WebSocketConfig.java
+++ b/src/main/java/com/youlai/system/config/WebSocketConfig.java
@@ -63,6 +63,8 @@ public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
/**
* 配置客户端入站通道拦截器
+ *
+ * 添加 ChannelInterceptor 拦截器,用于在消息发送前,从请求头中获取 token 并解析出用户信息(username),用于点对点发送消息给指定用户
*
* @param registration 通道注册器
*/
@@ -72,37 +74,28 @@ public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public Message> preSend(Message> message, MessageChannel channel) {
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
-
- // 如果 StompHeaderAccessor 为 null,说明不是 STOMP 消息,直接放行
- if (accessor == null) {
- return ChannelInterceptor.super.preSend(message, channel);
- }
-
// 如果是连接请求(CONNECT 命令),从请求头中取出 token 并设置到认证信息中
- if (StompCommand.CONNECT.equals(accessor.getCommand())) {
+ if (accessor != null && StompCommand.CONNECT.equals(accessor.getCommand())) {
// 从连接头中提取授权令牌
String bearerToken = accessor.getFirstNativeHeader(HttpHeaders.AUTHORIZATION);
// 验证令牌格式并提取用户信息
if (StrUtil.isNotBlank(bearerToken) && bearerToken.startsWith("Bearer ")) {
try {
- // 移除 "Bearer " 前缀
+ // 移除 "Bearer " 前缀,从令牌中提取用户信息(username), 并设置到认证信息中
String tokenWithoutPrefix = bearerToken.substring(7);
String username = jwtTokenProvider.getUsername(tokenWithoutPrefix);
- // 如果用户名有效,设置用户到访问器中
if (StrUtil.isNotBlank(username)) {
accessor.setUser(() -> username);
return message;
}
} catch (Exception e) {
- // 异常处理,可能是解析令牌失败
log.error("Failed to process authentication token.", e);
}
}
}
-
- // 如果不是连接命令或授权失败,继续执行默认逻辑
+ // 不是连接请求,直接放行
return ChannelInterceptor.super.preSend(message, channel);
}
});
diff --git a/src/main/java/com/youlai/system/controller/WebsocketController.java b/src/main/java/com/youlai/system/controller/WebsocketController.java
index ed82a66e..0b0d1fe0 100644
--- a/src/main/java/com/youlai/system/controller/WebsocketController.java
+++ b/src/main/java/com/youlai/system/controller/WebsocketController.java
@@ -54,7 +54,7 @@ public class WebsocketController {
String receiver = username; // 接收人
log.info("发送人:{}; 接收人:{}", sender, receiver);
- // 发送消息给指定用户 /user/{username}/queue/greeting
+ // 发送消息给指定用户,拼接后路径 /user/{receiver}/queue/greeting
messagingTemplate.convertAndSendToUser(receiver, "/queue/greeting", new ChatMessage(sender, message));
}
From 31a2fbeb422f113f4ede8bde53d1f2a670bc4c39 Mon Sep 17 00:00:00 2001
From: haoxr <1490493387@qq.com>
Date: Fri, 15 Dec 2023 23:43:09 +0800
Subject: [PATCH 3/4] =?UTF-8?q?refactor:=20knife4j=20=E5=85=A8=E5=B1=80?=
=?UTF-8?q?=E8=AE=BE=E7=BD=AE=E5=8F=82=E6=95=B0=E6=8E=92=E9=99=A4=E6=97=A0?=
=?UTF-8?q?=E9=9C=80=E9=89=B4=E6=9D=83=E7=9A=84=E6=8E=A5=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../youlai/system/config/SwaggerConfig.java | 43 +++++++++++++++----
1 file changed, 35 insertions(+), 8 deletions(-)
diff --git a/src/main/java/com/youlai/system/config/SwaggerConfig.java b/src/main/java/com/youlai/system/config/SwaggerConfig.java
index e557f3e8..86a91b54 100644
--- a/src/main/java/com/youlai/system/config/SwaggerConfig.java
+++ b/src/main/java/com/youlai/system/config/SwaggerConfig.java
@@ -5,9 +5,12 @@ import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
import org.springframework.http.HttpHeaders;
/**
@@ -19,19 +22,26 @@ import org.springframework.http.HttpHeaders;
* @since 2023/2/17
*/
@Configuration
+@Slf4j
+@RequiredArgsConstructor
public class SwaggerConfig {
+ private final Environment environment;
+
/**
* 接口信息
*/
@Bean
public OpenAPI openApi() {
+
+ String appVersion = environment.getProperty("project.version", "1.0.0");
+
return new OpenAPI()
.info(new Info()
.title("系统接口文档")
- .version("2.4.0")
+ .version(appVersion)
)
- // 全局安全校验项,也可以在对应的controller上加注解SecurityRequirement
+ // 配置全局鉴权参数-Authorize
.components(new Components()
.addSecuritySchemes(HttpHeaders.AUTHORIZATION,
new SecurityScheme()
@@ -41,17 +51,34 @@ public class SwaggerConfig {
.scheme("Bearer")
.bearerFormat("JWT")
)
- )
- .addSecurityItem(new SecurityRequirement().addList(HttpHeaders.AUTHORIZATION)) ;
+ );
}
+ /**
+ * 全局自定义扩展
+ *
+ * 在OpenAPI规范中,Operation 是一个表示 API 端点(Endpoint)或操作的对象。
+ * 每个路径(Path)对象可以包含一个或多个 Operation 对象,用于描述与该路径相关联的不同 HTTP 方法(例如 GET、POST、PUT 等)。
+ */
@Bean
public GlobalOpenApiCustomizer globalOpenApiCustomizer() {
- return openApi -> openApi.getPaths().values()
- .stream()
- .flatMap(pathItem -> pathItem.readOperations().stream())
- .forEach(operation -> operation.security(openApi.getSecurity()));
+ return openApi -> {
+ // 全局添加鉴权参数
+ if (openApi.getPaths() != null) {
+ openApi.getPaths().forEach((s, pathItem) -> {
+ // 登录接口/验证码不需要添加鉴权参数
+ if (s.equals("/api/v1/auth/login") || s.equals("/api/v1/auth/captcha")) {
+ return;
+ }
+ // 接口添加鉴权参数
+ pathItem.readOperations()
+ .forEach(operation ->
+ operation.addSecurityItem(new SecurityRequirement().addList(HttpHeaders.AUTHORIZATION))
+ );
+ });
+ }
+ };
}
}
From a1a1a64f7376492fba35a74396c3ba258befd579 Mon Sep 17 00:00:00 2001
From: haoxr <1490493387@qq.com>
Date: Sat, 16 Dec 2023 14:10:42 +0800
Subject: [PATCH 4/4] =?UTF-8?q?refactor:=20=E9=AA=8C=E8=AF=81=E7=A0=81?=
=?UTF-8?q?=E9=87=8D=E6=9E=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../system/plugin/captcha/CaptchaConfig.java | 55 ++++++++++++
.../plugin/captcha/CaptchaGenerator.java | 87 -------------------
.../system/plugin/captcha/CaptchaModel.java | 24 -----
.../plugin/captcha/CaptchaProperties.java | 5 ++
.../websocket/WebSocketEventListener.java | 68 ---------------
.../system/service/impl/AuthServiceImpl.java | 39 +++++++--
src/main/resources/application-dev.yml | 8 +-
src/main/resources/application-prod.yml | 8 +-
8 files changed, 103 insertions(+), 191 deletions(-)
create mode 100644 src/main/java/com/youlai/system/plugin/captcha/CaptchaConfig.java
delete mode 100644 src/main/java/com/youlai/system/plugin/captcha/CaptchaGenerator.java
delete mode 100644 src/main/java/com/youlai/system/plugin/captcha/CaptchaModel.java
delete mode 100644 src/main/java/com/youlai/system/plugin/websocket/WebSocketEventListener.java
diff --git a/src/main/java/com/youlai/system/plugin/captcha/CaptchaConfig.java b/src/main/java/com/youlai/system/plugin/captcha/CaptchaConfig.java
new file mode 100644
index 00000000..daf6fd35
--- /dev/null
+++ b/src/main/java/com/youlai/system/plugin/captcha/CaptchaConfig.java
@@ -0,0 +1,55 @@
+package com.youlai.system.plugin.captcha;
+
+import cn.hutool.captcha.*;
+import cn.hutool.captcha.generator.CodeGenerator;
+import cn.hutool.captcha.generator.MathGenerator;
+import cn.hutool.captcha.generator.RandomGenerator;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.awt.*;
+
+/**
+ * 验证码自动装配配置
+ *
+ * @author haoxr
+ * @since 2023/11/24
+ */
+@Configuration
+public class CaptchaConfig {
+
+ @Autowired
+ private CaptchaProperties captchaProperties;
+
+ /**
+ * 验证码文字生成器
+ *
+ * @return CodeGenerator
+ */
+ @Bean
+ public CodeGenerator codeGenerator() {
+ String codeType = captchaProperties.getCode().getType();
+ int codeLength = captchaProperties.getCode().getLength();
+ if ("math".equalsIgnoreCase(codeType)) {
+ return new MathGenerator(codeLength);
+ } else if ("random".equalsIgnoreCase(codeType)) {
+ return new RandomGenerator(codeLength);
+ } else {
+ throw new IllegalArgumentException("Invalid captcha generator type: " + codeType);
+ }
+ }
+
+ /**
+ * 验证码字体
+ */
+ @Bean
+ public Font captchaFont() {
+ String fontName = captchaProperties.getFont().getName();
+ int fontSize = captchaProperties.getFont().getSize();
+ int fontWight = captchaProperties.getFont().getWeight();
+ return new Font(fontName, fontWight, fontSize);
+ }
+
+
+}
diff --git a/src/main/java/com/youlai/system/plugin/captcha/CaptchaGenerator.java b/src/main/java/com/youlai/system/plugin/captcha/CaptchaGenerator.java
deleted file mode 100644
index 6ea870df..00000000
--- a/src/main/java/com/youlai/system/plugin/captcha/CaptchaGenerator.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.youlai.system.plugin.captcha;
-
-import cn.hutool.captcha.AbstractCaptcha;
-import cn.hutool.captcha.CircleCaptcha;
-import cn.hutool.captcha.generator.CodeGenerator;
-import cn.hutool.captcha.generator.MathGenerator;
-import cn.hutool.captcha.generator.RandomGenerator;
-import com.youlai.system.model.dto.CaptchaResult;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * 验证码自动装配配置
- *
- * @author haoxr
- * @since 2023/11/24
- */
-@Configuration
-public class CaptchaGenerator {
-
- @Autowired
- private CaptchaProperties captchaProperties;
-
- /**
- * 验证码文字生成器
- *
- * @return CodeGenerator
- */
- @Bean
- public CodeGenerator codeGenerator() {
- String codeType = captchaProperties.getCode().getType();
- int codeLength = captchaProperties.getCode().getLength();
- if ("math".equalsIgnoreCase(codeType)) {
- return new MathGenerator(codeLength);
- } else if ("random".equalsIgnoreCase(codeType)) {
- return new RandomGenerator(codeLength);
- } else {
- throw new IllegalArgumentException("Invalid captcha generator type: " + codeType);
- }
- }
-
-
- /**
- * 生成验证码
- *
- * @return CaptchaModel 验证码
- */
- public CaptchaModel generate() {
- AbstractCaptcha captcha = getCaptcha();
- captcha.createCode();
- return new CaptchaModel(captcha.getCode(), captcha.getImageBase64Data());
- }
-
- /**
- * 验证码类
- *
- * @return AbstractCaptcha
- */
- public AbstractCaptcha getCaptcha() {
- AbstractCaptcha captcha = null;
-
- String type = captchaProperties.getType();
- int width = captchaProperties.getWidth();
- int height = captchaProperties.getHeight();
- int interfereCount = captchaProperties.getInterfereCount();
- int codeLength = captchaProperties.getCode().getLength();
-
-
- if ("circle".equalsIgnoreCase(type)) {
- captcha = new CircleCaptcha(width, height, codeLength, interfereCount);
- } else if ("gif".equalsIgnoreCase(type)) {
- return null;
- } else if ("line".equalsIgnoreCase(type)) {
- return null;
- } else if ("shear".equalsIgnoreCase(type)) {
- return null;
- } else {
- throw new IllegalArgumentException("Invalid captcha type: " + type);
- }
-
- captcha.setGenerator(codeGenerator());
- return captcha;
- }
-
-
-}
diff --git a/src/main/java/com/youlai/system/plugin/captcha/CaptchaModel.java b/src/main/java/com/youlai/system/plugin/captcha/CaptchaModel.java
deleted file mode 100644
index cdbc9e44..00000000
--- a/src/main/java/com/youlai/system/plugin/captcha/CaptchaModel.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.youlai.system.plugin.captcha;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * 验证码对象
- */
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class CaptchaModel {
- /**
- * 验证码编码
- */
- private String code;
-
- /**
- * 验证码图片Base64
- */
- private String base64;
-
-}
diff --git a/src/main/java/com/youlai/system/plugin/captcha/CaptchaProperties.java b/src/main/java/com/youlai/system/plugin/captcha/CaptchaProperties.java
index 1653a708..9b32f1a5 100644
--- a/src/main/java/com/youlai/system/plugin/captcha/CaptchaProperties.java
+++ b/src/main/java/com/youlai/system/plugin/captcha/CaptchaProperties.java
@@ -34,6 +34,11 @@ public class CaptchaProperties {
*/
private int interfereCount;
+ /**
+ * 文本透明度
+ */
+ private Float textAlpha;
+
/**
* 验证码过期时间,单位:秒
*/
diff --git a/src/main/java/com/youlai/system/plugin/websocket/WebSocketEventListener.java b/src/main/java/com/youlai/system/plugin/websocket/WebSocketEventListener.java
deleted file mode 100644
index e4189d0b..00000000
--- a/src/main/java/com/youlai/system/plugin/websocket/WebSocketEventListener.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.youlai.system.plugin.websocket;
-
-import cn.hutool.json.JSONUtil;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.event.EventListener;
-import org.springframework.stereotype.Component;
-import org.springframework.web.socket.messaging.SessionConnectedEvent;
-import org.springframework.web.socket.messaging.SessionDisconnectEvent;
-import org.springframework.web.socket.messaging.SessionSubscribeEvent;
-import org.springframework.web.socket.messaging.SessionUnsubscribeEvent;
-
-import java.security.Principal;
-
-/**
- * Websocket 客户端事件监听器
- *
- * @author haoxr
- * @since 2023/10/10
- */
-@Component
-@Slf4j
-public class WebSocketEventListener {
-
- /**
- * 监听客户端连接事件
- *
- * @param event 连接事件对象
- */
- @EventListener
- public void handleWebSocketConnectListener(SessionConnectedEvent event) {
- Principal user = event.getUser();
-
- log.info("客户端连接成功");
- }
-
- /**
- * 监听客户端断开连接事件
- *
- * @param event 断开连接事件对象
- */
- @EventListener
- public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) {
- log.info("客户端断开连接");
- }
-
-
- /**
- * 监听客户端订阅事件
- *
- * @param event 订阅事件对象
- */
- @EventListener
- public void handleSubscription(SessionSubscribeEvent event) {
- log.info("客户端订阅:{}", JSONUtil.toJsonStr(event.getMessage()));
- }
-
- /**
- * 监听客户端取消订阅事件
- *
- * @param event 取消订阅事件对象
- */
- @EventListener
- public void handleUnSubscription(SessionUnsubscribeEvent event) {
- log.info("客户端取消订阅:{}", JSONUtil.toJsonStr(event.getMessage()));
- }
-
-
-}
diff --git a/src/main/java/com/youlai/system/service/impl/AuthServiceImpl.java b/src/main/java/com/youlai/system/service/impl/AuthServiceImpl.java
index a34e4ed5..ae00fb76 100644
--- a/src/main/java/com/youlai/system/service/impl/AuthServiceImpl.java
+++ b/src/main/java/com/youlai/system/service/impl/AuthServiceImpl.java
@@ -1,13 +1,14 @@
package com.youlai.system.service.impl;
+import cn.hutool.captcha.AbstractCaptcha;
+import cn.hutool.captcha.CaptchaUtil;
+import cn.hutool.captcha.generator.CodeGenerator;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.youlai.system.common.constant.CacheConstants;
import com.youlai.system.core.security.jwt.JwtTokenProvider;
import com.youlai.system.model.dto.CaptchaResult;
import com.youlai.system.model.dto.LoginResult;
-import com.youlai.system.plugin.captcha.CaptchaGenerator;
-import com.youlai.system.plugin.captcha.CaptchaModel;
import com.youlai.system.plugin.captcha.CaptchaProperties;
import com.youlai.system.service.AuthService;
import io.jsonwebtoken.Claims;
@@ -22,6 +23,7 @@ import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
+import java.awt.*;
import java.util.Date;
import java.util.concurrent.TimeUnit;
@@ -38,7 +40,8 @@ public class AuthServiceImpl implements AuthService {
private final AuthenticationManager authenticationManager;
private final StringRedisTemplate redisTemplate;
private final JwtTokenProvider jwtTokenProvider;
- private final CaptchaGenerator captchaGenerator;
+ private final CodeGenerator codeGenerator;
+ private final Font captchaFont;
private final CaptchaProperties captchaProperties;
/**
@@ -88,16 +91,40 @@ public class AuthServiceImpl implements AuthService {
*/
@Override
public CaptchaResult getCaptcha() {
- CaptchaModel captchaModel = captchaGenerator.generate();
+
+ String type = captchaProperties.getType();
+ int width = captchaProperties.getWidth();
+ int height = captchaProperties.getHeight();
+ int interfereCount = captchaProperties.getInterfereCount();
+ int codeLength = captchaProperties.getCode().getLength();
+
+ AbstractCaptcha captcha;
+ if ("circle".equalsIgnoreCase(type)) {
+ captcha = CaptchaUtil.createCircleCaptcha(width, height, codeLength, interfereCount);
+ } else if ("gif".equalsIgnoreCase(type)) {
+ captcha = CaptchaUtil.createGifCaptcha(width, height, codeLength);
+ } else if ("line".equalsIgnoreCase(type)) {
+ captcha = CaptchaUtil.createLineCaptcha(width, height, codeLength, interfereCount);
+ } else if ("shear".equalsIgnoreCase(type)) {
+ captcha = CaptchaUtil.createShearCaptcha(width, height, codeLength, interfereCount);
+ } else {
+ throw new IllegalArgumentException("Invalid captcha type: " + type);
+ }
+ captcha.setGenerator(codeGenerator);
+ captcha.setTextAlpha(captchaProperties.getTextAlpha());
+ captcha.setFont(captchaFont);
+
+ String captchaCode = captcha.getCode();
+ String imageBase64Data = captcha.getImageBase64Data();
// 验证码文本缓存至Redis,用于登录校验
String captchaKey = IdUtil.fastSimpleUUID();
- redisTemplate.opsForValue().set(CacheConstants.CAPTCHA_CODE_PREFIX + captchaKey, captchaModel.getCode(),
+ redisTemplate.opsForValue().set(CacheConstants.CAPTCHA_CODE_PREFIX + captchaKey,captchaCode,
captchaProperties.getExpireSeconds(), TimeUnit.SECONDS);
return CaptchaResult.builder()
.captchaKey(captchaKey)
- .captchaBase64(captchaModel.getBase64())
+ .captchaBase64(imageBase64Data)
.build();
}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 67c32380..e6dff2eb 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -136,10 +136,12 @@ captcha:
# 验证码高度
height: 40
# 验证码干扰元素个数
- interfere-count: 3
+ interfere-count: 4
+ # 文本透明度(0.0-1.0)
+ text-alpha: 0.8
# 验证码字符配置
code:
- # 验证码字符类型 math-算术 |random-随机字符
+ # 验证码字符类型 math-算术|random-随机字符
type: math
# 验证码字符长度,type=算术时,表示运算位数(1:个位数运算 2:十位数运算);type=随机字符时,表示字符个数
length: 1
@@ -150,7 +152,7 @@ captcha:
# 字体样式 0-普通|1-粗体|2-斜体
weight: 1
# 字体大小
- size: 18
+ size: 30
# 验证码有效期(秒)
expire-seconds: 120
diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml
index 1869f002..8ce1f49c 100644
--- a/src/main/resources/application-prod.yml
+++ b/src/main/resources/application-prod.yml
@@ -136,10 +136,12 @@ captcha:
# 验证码高度
height: 40
# 验证码干扰元素个数
- interfere-count: 3
+ interfere-count: 4
+ # 文本透明度(0.0-1.0)
+ text-alpha: 0.8
# 验证码字符配置
code:
- # 验证码字符类型 math-算术 |random-随机字符
+ # 验证码字符类型 math-算术|random-随机字符
type: math
# 验证码字符长度,type=算术时,表示运算位数(1:个位数运算 2:十位数运算);type=随机字符时,表示字符个数
length: 1
@@ -150,7 +152,7 @@ captcha:
# 字体样式 0-普通|1-粗体|2-斜体
weight: 1
# 字体大小
- size: 18
+ size: 30
# 验证码有效期(秒)
expire-seconds: 120