fix: sse修改

This commit is contained in:
2026-06-24 10:40:28 +08:00
parent 3580ad934e
commit 61ff5d46e6
2 changed files with 39 additions and 2 deletions

View File

@@ -31,6 +31,7 @@ public class SaTokenConfigure implements WebMvcConfigurer {
.notMatch("/v3/api-docs/**") .notMatch("/v3/api-docs/**")
.notMatch("/webjars/**") .notMatch("/webjars/**")
.notMatch("/error") .notMatch("/error")
.notMatch("/sse/**")
.check(r -> StpUtil.checkLogin()); .check(r -> StpUtil.checkLogin());
})).addPathPatterns("/**") })).addPathPatterns("/**")
.excludePathPatterns("/error"); .excludePathPatterns("/error");

View File

@@ -1,6 +1,7 @@
package com.webgame.webgamebackend.sse; package com.webgame.webgamebackend.sse;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
@@ -31,8 +32,26 @@ public class SseController {
@GetMapping(value = "/subscribe", produces = MediaType.TEXT_EVENT_STREAM_VALUE) @GetMapping(value = "/subscribe", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter subscribe( public SseEmitter subscribe(
@RequestHeader(value = "Last-Event-ID", required = false) String lastEventId) { @RequestHeader(value = "Last-Event-ID", required = false) String lastEventId,
String userId = StpUtil.getLoginIdAsString(); 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); SseEmitter emitter = new SseEmitter(SSE_TIMEOUT_MS);
String connectionId = connectionManager.register(userId, emitter); String connectionId = connectionManager.register(userId, emitter);
@@ -56,4 +75,21 @@ public class SseController {
userId, connectionId, connectionManager.getOnlineCount()); userId, connectionId, connectionManager.getOnlineCount());
return emitter; 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;
}
} }