diff --git a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java index 43e689be3..c4b9feae8 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java @@ -18,7 +18,7 @@ import org.dromara.common.core.domain.model.SocialLoginBody; import org.dromara.common.core.utils.*; import org.dromara.common.encrypt.annotation.ApiEncrypt; import org.dromara.common.json.utils.JsonUtils; -import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.common.satoken.utils.TokenUtils; import org.dromara.common.social.config.properties.SocialLoginConfigProperties; import org.dromara.common.social.config.properties.SocialProperties; import org.dromara.common.social.utils.SocialUtils; @@ -95,11 +95,11 @@ public class AuthController { // 登录 LoginVo loginVo = IAuthStrategy.login(body, client, grantType); - Long userId = LoginHelper.getUserId(); + String tokenId = TokenUtils.getTokenId(); scheduledExecutorService.schedule(() -> { WebSocketMessageDto dto = new WebSocketMessageDto(); dto.setMessage("欢迎登录RuoYi-Vue-Plus后台管理系统"); - dto.setSessionKeys(List.of(userId)); + dto.setSessionKeys(List.of(tokenId)); WebSocketUtils.publishMessage(dto); }, 3, TimeUnit.SECONDS); return R.ok(loginVo); @@ -198,7 +198,7 @@ public class AuthController { } // 根据域名进行筛选 List list = StreamUtils.filter(voList, vo -> - StringUtils.equals(vo.getDomain(), host)); + StringUtils.equals(vo.getDomain(), host)); // 返回对象 LoginTenantVo vo = new LoginTenantVo(); vo.setVoList(CollUtil.isNotEmpty(list) ? list : voList); diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/TokenUtils.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/TokenUtils.java new file mode 100644 index 000000000..d005851ab --- /dev/null +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/TokenUtils.java @@ -0,0 +1,88 @@ +package org.dromara.common.satoken.utils; + +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.dromara.common.core.enums.DeviceType; + +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * token工具类 + * + * @author 21001 + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class TokenUtils { + + /** + * 会话id(loginId)前缀 + */ + public static final String SYS_USER = "sys_user:"; + + /** + * 获取当前登录用户的token + */ + public static String getTokenId() { + return StpUtil.getTokenInfo().getTokenValue(); + } + + /** + * 获取当前用户的 token 集合 + */ + public static List getTokenIds() { + return StpUtil.getTokenValueListByLoginId(SYS_USER + LoginHelper.getUserId()); + } + + /** + * 获取当前用户 指定设备类型端的 token 集合 + */ + public static List getTokenIds(DeviceType device) { + return StpUtil.getTokenValueListByLoginId(SYS_USER + LoginHelper.getUserId(), device.getDevice()); + } + + /** + * 获取指定账号 userId 的 token 集合 + */ + public static List getTokenIds(Long userId) { + return StpUtil.getTokenValueListByLoginId(SYS_USER + userId); + } + + /** + * 获取账号 userId 指定设备类型端的 token 集合 + */ + public static List getTokenIds(Long userId, DeviceType device) { + return StpUtil.getTokenValueListByLoginId(SYS_USER + userId, device.getDevice()); + } + + /** + * 获取指定账号 userIds 的 token 集合 + */ + public static List getTokenUserIds(Set userIds) { + if (CollUtil.isEmpty(userIds)) { + return Collections.emptyList(); + } + return userIds.stream() + .flatMap(userId -> StpUtil.getTokenValueListByLoginId(SYS_USER + userId) + .stream()) + .collect(Collectors.toList()); + } + + /** + * 获取账号 userIds 指定设备类型端的 token 集合 + */ + public static List getTokenUserIds(Set userIds, DeviceType device) { + if (CollUtil.isEmpty(userIds)) { + return Collections.emptyList(); + } + return userIds.stream() + .flatMap(userId -> StpUtil.getTokenValueListByLoginId(SYS_USER + userId, device.getDevice()) + .stream()) + .collect(Collectors.toList()); + } + +} diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/constant/WebSocketConstants.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/constant/WebSocketConstants.java index 54eb4470b..a700b335a 100644 --- a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/constant/WebSocketConstants.java +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/constant/WebSocketConstants.java @@ -6,10 +6,12 @@ package org.dromara.common.websocket.constant; * @author zendwang */ public interface WebSocketConstants { + /** * websocketSession中的参数的key */ String LOGIN_USER_KEY = "loginUser"; + String TOKEN_ID_KEY = "tokenId"; /** * 订阅的频道 diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/dto/WebSocketMessageDto.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/dto/WebSocketMessageDto.java index e2d4456a0..3440988b1 100644 --- a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/dto/WebSocketMessageDto.java +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/dto/WebSocketMessageDto.java @@ -18,9 +18,9 @@ public class WebSocketMessageDto implements Serializable { private static final long serialVersionUID = 1L; /** - * 需要推送到的session key 列表 + * 需要推送到的session key 列表 一般为用户tokenId */ - private List sessionKeys; + private List sessionKeys; /** * 需要发送的消息 diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/handler/PlusWebSocketHandler.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/handler/PlusWebSocketHandler.java index a53583f19..0845a88bd 100644 --- a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/handler/PlusWebSocketHandler.java +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/handler/PlusWebSocketHandler.java @@ -2,6 +2,7 @@ package org.dromara.common.websocket.handler; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.domain.model.LoginUser; +import org.dromara.common.satoken.utils.TokenUtils; import org.dromara.common.websocket.dto.WebSocketMessageDto; import org.dromara.common.websocket.holder.WebSocketSessionHolder; import org.dromara.common.websocket.utils.WebSocketUtils; @@ -11,6 +12,7 @@ import org.springframework.web.socket.handler.AbstractWebSocketHandler; import java.util.List; import static org.dromara.common.websocket.constant.WebSocketConstants.LOGIN_USER_KEY; +import static org.dromara.common.websocket.constant.WebSocketConstants.TOKEN_ID_KEY; /** * WebSocketHandler 实现类 @@ -26,7 +28,8 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler { @Override public void afterConnectionEstablished(WebSocketSession session) { LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY); - WebSocketSessionHolder.addSession(loginUser.getUserId(), session); + String tokenId = (String) session.getAttributes().get(TOKEN_ID_KEY); + WebSocketSessionHolder.addSession(tokenId, session); log.info("[connect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType()); } @@ -40,9 +43,9 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler { @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY); - List userIds = List.of(loginUser.getUserId()); + List tokenIds = TokenUtils.getTokenIds(loginUser.getUserId()); WebSocketMessageDto webSocketMessageDto = new WebSocketMessageDto(); - webSocketMessageDto.setSessionKeys(userIds); + webSocketMessageDto.setSessionKeys(tokenIds); webSocketMessageDto.setMessage(message.getPayload()); WebSocketUtils.publishMessage(webSocketMessageDto); } @@ -85,7 +88,8 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler { @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY); - WebSocketSessionHolder.removeSession(loginUser.getUserId()); + String tokenId = (String) session.getAttributes().get(TOKEN_ID_KEY); + WebSocketSessionHolder.removeSession(tokenId); log.info("[disconnect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType()); } diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java index de8c5a758..67580381a 100644 --- a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java @@ -16,27 +16,31 @@ import java.util.concurrent.ConcurrentHashMap; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class WebSocketSessionHolder { - private static final Map USER_SESSION_MAP = new ConcurrentHashMap<>(); + private static final Map USER_SESSION_MAP = new ConcurrentHashMap<>(); - public static void addSession(Long sessionKey, WebSocketSession session) { + /** + * @param sessionKey session主键 一般为用户tokenId + * @param session 会话 + */ + public static void addSession(String sessionKey, WebSocketSession session) { USER_SESSION_MAP.put(sessionKey, session); } - public static void removeSession(Long sessionKey) { + public static void removeSession(String sessionKey) { if (USER_SESSION_MAP.containsKey(sessionKey)) { USER_SESSION_MAP.remove(sessionKey); } } - public static WebSocketSession getSessions(Long sessionKey) { + public static WebSocketSession getSessions(String sessionKey) { return USER_SESSION_MAP.get(sessionKey); } - public static Set getSessionsAll() { + public static Set getSessionsAll() { return USER_SESSION_MAP.keySet(); } - public static Boolean existSession(Long sessionKey) { + public static Boolean existSession(String sessionKey) { return USER_SESSION_MAP.containsKey(sessionKey); } } diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/interceptor/PlusWebSocketInterceptor.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/interceptor/PlusWebSocketInterceptor.java index 1dc4120db..5a114fa4f 100644 --- a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/interceptor/PlusWebSocketInterceptor.java +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/interceptor/PlusWebSocketInterceptor.java @@ -1,8 +1,9 @@ package org.dromara.common.websocket.interceptor; +import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.satoken.utils.LoginHelper; -import lombok.extern.slf4j.Slf4j; +import org.dromara.common.satoken.utils.TokenUtils; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.socket.WebSocketHandler; @@ -11,6 +12,7 @@ import org.springframework.web.socket.server.HandshakeInterceptor; import java.util.Map; import static org.dromara.common.websocket.constant.WebSocketConstants.LOGIN_USER_KEY; +import static org.dromara.common.websocket.constant.WebSocketConstants.TOKEN_ID_KEY; /** * WebSocket握手请求的拦截器 @@ -32,7 +34,9 @@ public class PlusWebSocketInterceptor implements HandshakeInterceptor { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes) { LoginUser loginUser = LoginHelper.getLoginUser(); + String tokenId = TokenUtils.getTokenId(); attributes.put(LOGIN_USER_KEY, loginUser); + attributes.put(TOKEN_ID_KEY, tokenId); return true; } diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/utils/WebSocketUtils.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/utils/WebSocketUtils.java index 086599c40..d8b0a4bf3 100644 --- a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/utils/WebSocketUtils.java +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/utils/WebSocketUtils.java @@ -31,10 +31,10 @@ public class WebSocketUtils { /** * 发送消息 * - * @param sessionKey session主键 一般为用户id + * @param sessionKey session主键 一般为用户tokenId * @param message 消息文本 */ - public static void sendMessage(Long sessionKey, String message) { + public static void sendMessage(String sessionKey, String message) { WebSocketSession session = WebSocketSessionHolder.getSessions(sessionKey); sendMessage(session, message); } @@ -54,9 +54,9 @@ public class WebSocketUtils { * @param webSocketMessage 消息对象 */ public static void publishMessage(WebSocketMessageDto webSocketMessage) { - List unsentSessionKeys = new ArrayList<>(); + List unsentSessionKeys = new ArrayList<>(); // 当前服务内session,直接发送消息 - for (Long sessionKey : webSocketMessage.getSessionKeys()) { + for (String sessionKey : webSocketMessage.getSessionKeys()) { if (WebSocketSessionHolder.existSession(sessionKey)) { WebSocketUtils.sendMessage(sessionKey, webSocketMessage.getMessage()); continue; diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java index 6979671e2..f82e36b47 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java @@ -12,6 +12,7 @@ import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.reflect.ReflectUtils; import org.dromara.common.mail.utils.MailUtils; +import org.dromara.common.satoken.utils.TokenUtils; import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.common.websocket.dto.WebSocketMessageDto; import org.dromara.common.websocket.utils.WebSocketUtils; @@ -23,10 +24,13 @@ import org.dromara.workflow.common.enums.MessageTypeEnum; import org.dromara.workflow.common.enums.TaskStatusEnum; import org.dromara.workflow.domain.ActHiProcinst; import org.dromara.workflow.domain.ActHiTaskinst; -import org.dromara.workflow.domain.vo.*; +import org.dromara.workflow.domain.vo.MultiInstanceVo; +import org.dromara.workflow.domain.vo.ParticipantVo; +import org.dromara.workflow.domain.vo.ProcessInstanceVo; import org.dromara.workflow.flowable.cmd.UpdateHiTaskInstCmd; import org.dromara.workflow.mapper.ActHiTaskinstMapper; -import org.dromara.workflow.service.*; +import org.dromara.workflow.service.IActHiProcinstService; +import org.dromara.workflow.service.IWorkflowUserService; import org.flowable.bpmn.model.BpmnModel; import org.flowable.bpmn.model.FlowNode; import org.flowable.common.engine.api.delegate.Expression; @@ -41,7 +45,7 @@ import org.flowable.task.service.impl.persistence.entity.TaskEntity; import java.util.*; -import static org.dromara.workflow.common.constant.FlowConstant.*; +import static org.dromara.workflow.common.constant.FlowConstant.PROCESS_INSTANCE_VO; /** * 工作流工具 @@ -324,7 +328,7 @@ public class WorkflowUtils { switch (messageTypeEnum) { case SYSTEM_MESSAGE: WebSocketMessageDto dto = new WebSocketMessageDto(); - dto.setSessionKeys(new ArrayList<>(userIds)); + dto.setSessionKeys(TokenUtils.getTokenUserIds(userIds)); dto.setMessage(message); WebSocketUtils.publishMessage(dto); break;