fix: sse修改
This commit is contained in:
@@ -31,6 +31,7 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
||||
.notMatch("/v3/api-docs/**")
|
||||
.notMatch("/webjars/**")
|
||||
.notMatch("/error")
|
||||
.notMatch("/sse/**")
|
||||
.check(r -> StpUtil.checkLogin());
|
||||
})).addPathPatterns("/**")
|
||||
.excludePathPatterns("/error");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.webgame.webgamebackend.sse;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -31,8 +32,26 @@ public class SseController {
|
||||
|
||||
@GetMapping(value = "/subscribe", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
||||
public SseEmitter subscribe(
|
||||
@RequestHeader(value = "Last-Event-ID", required = false) String lastEventId) {
|
||||
String userId = StpUtil.getLoginIdAsString();
|
||||
@RequestHeader(value = "Last-Event-ID", required = false) String lastEventId,
|
||||
HttpServletResponse response) throws IOException {
|
||||
|
||||
// SSE 路径已排除在 SaInterceptor 之外,此处手动校验登录态
|
||||
String token = StpUtil.getTokenValue();
|
||||
if (token == null || token.isBlank()) {
|
||||
log.warn("[SSE] 缺少认证 token");
|
||||
return writeAuthError(response, HttpServletResponse.SC_UNAUTHORIZED, "缺少认证信息,请先登录");
|
||||
}
|
||||
|
||||
Object loginId = StpUtil.getLoginIdByToken(token);
|
||||
if (loginId == null) {
|
||||
log.warn("[SSE] token 无效或已过期");
|
||||
return writeAuthError(response, HttpServletResponse.SC_UNAUTHORIZED, "登录已过期,请重新登录");
|
||||
}
|
||||
|
||||
// 设置 Sa-Token 上下文,后续 StpUtil.getLoginIdAsString() 可用
|
||||
StpUtil.setTokenValue(token, -1);
|
||||
|
||||
String userId = loginId.toString();
|
||||
SseEmitter emitter = new SseEmitter(SSE_TIMEOUT_MS);
|
||||
String connectionId = connectionManager.register(userId, emitter);
|
||||
|
||||
@@ -56,4 +75,21 @@ public class SseController {
|
||||
userId, connectionId, connectionManager.getOnlineCount());
|
||||
return emitter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 向 SSE 客户端返回认证错误
|
||||
*
|
||||
* 直接写入 HttpServletResponse 返回 401 + SSE error 事件,
|
||||
* 前端 SseClient.onopen 检测到 response.status === 401 后触发 onUnauthorized,
|
||||
* 自动刷新 token 并重连。
|
||||
*
|
||||
* @return null,通知 Spring MVC 响应已处理完毕,无需 MessageConverter
|
||||
*/
|
||||
private SseEmitter writeAuthError(HttpServletResponse response, int status, String message) throws IOException {
|
||||
response.setStatus(status);
|
||||
response.setContentType(MediaType.TEXT_EVENT_STREAM_VALUE);
|
||||
response.getWriter().write("event: error\ndata: {\"code\":" + status + ",\"message\":\"" + message + "\"}\n\n");
|
||||
response.getWriter().flush();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user