mirror of
https://gitcode.com/ageerle/ruoyi-ai.git
synced 2026-04-13 03:45:14 +00:00
[fix][feat](chat): 添加会话中SaToken-token值传递和使用;修复“自动注入警告 => 用户未登录”
- 新增 BaseContext 类,用于保存和获取当前登录用户的 token - 在 OpenAIServiceImpl 和 imageServiceImpl 中获取当前会话 token - 将 token 作为参数传递给 SSEEventSourceListener - 在 SSEEventSourceListener 中使用 token 进行用户身份验证和权限控制 - 修改 LoginHelper,增加根据 token 获取登录用户信息的方法 - 更新 InjectionMetaObjectHandler,使用 BaseContext 获取当前 token - 修复对话时出先”自动注入警告 => 用户未登录“
This commit is contained in:
@@ -0,0 +1,25 @@
|
|||||||
|
package org.ruoyi.common.core.service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 基于ThreadLocal封装工具类,用户保存和获取当前登录用户Sa-Token token值
|
||||||
|
* @author: yzm
|
||||||
|
**/
|
||||||
|
public class BaseContext {
|
||||||
|
private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 设置值
|
||||||
|
* @author: yzm
|
||||||
|
* @param: [token] 线程token
|
||||||
|
**/
|
||||||
|
public static void setCurrentToken(String token){
|
||||||
|
threadLocal.set(token);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @description: 获取值
|
||||||
|
* @author: yzm
|
||||||
|
**/
|
||||||
|
public static String getCurrentToken(){
|
||||||
|
return threadLocal.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.apache.ibatis.reflection.MetaObject;
|
import org.apache.ibatis.reflection.MetaObject;
|
||||||
import org.ruoyi.common.core.domain.model.LoginUser;
|
import org.ruoyi.common.core.domain.model.LoginUser;
|
||||||
import org.ruoyi.common.core.exception.ServiceException;
|
import org.ruoyi.common.core.exception.ServiceException;
|
||||||
|
import org.ruoyi.common.core.service.BaseContext;
|
||||||
import org.ruoyi.common.core.utils.ObjectUtils;
|
import org.ruoyi.common.core.utils.ObjectUtils;
|
||||||
import org.ruoyi.common.satoken.utils.LoginHelper;
|
import org.ruoyi.common.satoken.utils.LoginHelper;
|
||||||
import org.ruoyi.core.domain.BaseEntity;
|
import org.ruoyi.core.domain.BaseEntity;
|
||||||
@@ -91,7 +92,8 @@ public class InjectionMetaObjectHandler implements MetaObjectHandler {
|
|||||||
private LoginUser getLoginUser() {
|
private LoginUser getLoginUser() {
|
||||||
LoginUser loginUser;
|
LoginUser loginUser;
|
||||||
try {
|
try {
|
||||||
loginUser = LoginHelper.getLoginUser();
|
String token = BaseContext.getCurrentToken();
|
||||||
|
loginUser = LoginHelper.getLoginUser(token);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("自动注入警告 => 用户未登录");
|
log.warn("自动注入警告 => 用户未登录");
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -9,12 +9,16 @@ import cn.hutool.core.convert.Convert;
|
|||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.poi.ss.formula.functions.T;
|
||||||
import org.ruoyi.common.core.constant.TenantConstants;
|
import org.ruoyi.common.core.constant.TenantConstants;
|
||||||
import org.ruoyi.common.core.constant.UserConstants;
|
import org.ruoyi.common.core.constant.UserConstants;
|
||||||
import org.ruoyi.common.core.domain.model.LoginUser;
|
import org.ruoyi.common.core.domain.model.LoginUser;
|
||||||
import org.ruoyi.common.core.enums.DeviceType;
|
import org.ruoyi.common.core.enums.DeviceType;
|
||||||
import org.ruoyi.common.core.enums.UserType;
|
import org.ruoyi.common.core.enums.UserType;
|
||||||
|
import org.ruoyi.common.redis.utils.RedisUtils;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,6 +33,7 @@ import java.util.Set;
|
|||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public class LoginHelper {
|
public class LoginHelper {
|
||||||
|
|
||||||
@@ -82,6 +87,15 @@ public class LoginHelper {
|
|||||||
return loginUser;
|
return loginUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static <T extends LoginUser> T getLoginUser(String token) {
|
||||||
|
SaSession session = StpUtil.getTokenSessionByToken(token);
|
||||||
|
if (ObjectUtil.isNull(session)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (T) session.get(LOGIN_USER_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户id
|
* 获取用户id
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.ruoyi.chat.listener;
|
package org.ruoyi.chat.listener;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -15,6 +16,7 @@ import org.ruoyi.chat.service.chat.IChatCostService;
|
|||||||
import org.ruoyi.common.chat.entity.chat.ChatCompletionResponse;
|
import org.ruoyi.common.chat.entity.chat.ChatCompletionResponse;
|
||||||
import org.ruoyi.common.chat.entity.chat.Message;
|
import org.ruoyi.common.chat.entity.chat.Message;
|
||||||
import org.ruoyi.common.chat.request.ChatRequest;
|
import org.ruoyi.common.chat.request.ChatRequest;
|
||||||
|
import org.ruoyi.common.core.service.BaseContext;
|
||||||
import org.ruoyi.common.core.utils.SpringUtils;
|
import org.ruoyi.common.core.utils.SpringUtils;
|
||||||
import org.ruoyi.common.core.utils.StringUtils;
|
import org.ruoyi.common.core.utils.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -40,11 +42,14 @@ public class SSEEventSourceListener extends EventSourceListener {
|
|||||||
|
|
||||||
private Long sessionId;
|
private Long sessionId;
|
||||||
|
|
||||||
|
private String token;
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
public SSEEventSourceListener(SseEmitter emitter,Long userId,Long sessionId) {
|
public SSEEventSourceListener(SseEmitter emitter,Long userId,Long sessionId, String token) {
|
||||||
this.emitter = emitter;
|
this.emitter = emitter;
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
this.sessionId = sessionId;
|
this.sessionId = sessionId;
|
||||||
|
this.token = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -80,6 +85,8 @@ public class SSEEventSourceListener extends EventSourceListener {
|
|||||||
chatRequest.setUserId(userId);
|
chatRequest.setUserId(userId);
|
||||||
chatRequest.setSessionId(sessionId);
|
chatRequest.setSessionId(sessionId);
|
||||||
chatRequest.setPrompt(stringBuffer.toString());
|
chatRequest.setPrompt(stringBuffer.toString());
|
||||||
|
// 记录会话token
|
||||||
|
BaseContext.setCurrentToken(token);
|
||||||
chatCostService.deductToken(chatRequest);
|
chatCostService.deductToken(chatRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.ruoyi.chat.service.chat.impl;
|
package org.ruoyi.chat.service.chat.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.ruoyi.chat.config.ChatConfig;
|
import org.ruoyi.chat.config.ChatConfig;
|
||||||
@@ -127,8 +128,10 @@ public class ImageServiceImpl implements IChatService {
|
|||||||
OpenAiStreamClient openAiStreamClient = ChatConfig.createOpenAiStreamClient(chatModelVo.getApiHost(), chatModelVo.getApiKey());
|
OpenAiStreamClient openAiStreamClient = ChatConfig.createOpenAiStreamClient(chatModelVo.getApiHost(), chatModelVo.getApiKey());
|
||||||
List<Message> messages = chatRequest.getMessages();
|
List<Message> messages = chatRequest.getMessages();
|
||||||
|
|
||||||
|
// 获取会话token
|
||||||
|
String token = StpUtil.getTokenValue();
|
||||||
// 创建 SSE 事件源监听器
|
// 创建 SSE 事件源监听器
|
||||||
SSEEventSourceListener listener = new SSEEventSourceListener(emitter, chatRequest.getUserId(), chatRequest.getSessionId());
|
SSEEventSourceListener listener = new SSEEventSourceListener(emitter, chatRequest.getUserId(), chatRequest.getSessionId(), token);
|
||||||
|
|
||||||
// 构建聊天完成请求
|
// 构建聊天完成请求
|
||||||
ChatCompletion completion = ChatCompletion
|
ChatCompletion completion = ChatCompletion
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.ruoyi.chat.service.chat.impl;
|
package org.ruoyi.chat.service.chat.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
import io.modelcontextprotocol.client.McpSyncClient;
|
import io.modelcontextprotocol.client.McpSyncClient;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.ruoyi.chat.config.ChatConfig;
|
import org.ruoyi.chat.config.ChatConfig;
|
||||||
@@ -56,7 +57,8 @@ public class OpenAIServiceImpl implements IChatService {
|
|||||||
Message userMessage = Message.builder().content("工具返回信息:"+toolString).role(Message.Role.USER).build();
|
Message userMessage = Message.builder().content("工具返回信息:"+toolString).role(Message.Role.USER).build();
|
||||||
messages.add(userMessage);
|
messages.add(userMessage);
|
||||||
}
|
}
|
||||||
SSEEventSourceListener listener = new SSEEventSourceListener(emitter,chatRequest.getUserId(),chatRequest.getSessionId());
|
String token = StpUtil.getTokenValue();
|
||||||
|
SSEEventSourceListener listener = new SSEEventSourceListener(emitter,chatRequest.getUserId(),chatRequest.getSessionId(), token);
|
||||||
ChatCompletion completion = ChatCompletion
|
ChatCompletion completion = ChatCompletion
|
||||||
.builder()
|
.builder()
|
||||||
.messages(messages)
|
.messages(messages)
|
||||||
|
|||||||
Reference in New Issue
Block a user