Spring Websocket对接React Typescript提示需完整身份认证如何解决
问题原因
报错是两类安全校验拦截了请求:
- HTTP层面的JWT过滤器拦截了WebSocket握手请求,你当前配置下
/api/ws端点的请求需要携带有效认证信息才能访问 - WebSocket STOMP安全配置要求所有
/api/**路径的消息都需要认证才能处理
解决方案
方案1:允许WebSocket接口匿名访问(适合不需要登录就能用的场景)
- 首先修改Spring HTTP安全配置,放行WebSocket握手相关路径,避免被JWT过滤器拦截:
找到你项目中继承WebSecurityConfigurerAdapter的HTTP安全配置类,在configure(HttpSecurity http)方法中添加放行规则:
@Override protected void configure(HttpSecurity http) throws Exception { http // 保留你原有其他配置不变 .authorizeRequests() .antMatchers("/api/ws/**", "/sockjs/**").permitAll() .anyRequest().authenticated(); }
- 调整WebSocket STOMP安全配置,放行对应路径的消息:
修改你的WebSocketSecurityConfig类:
@Override protected void configureInbound(final MessageSecurityMetadataSourceRegistry messages) { messages.simpDestMatchers("/api/ws/**").permitAll() // 保留你其他原有规则 .anyMessage().authenticated(); }
方案2:WebSocket接口要求登录访问(适合需要身份校验的场景)
- 后端修改JWT过滤器逻辑,支持从URL请求参数中读取JWT令牌,因为SockJS发起握手请求时无法自定义请求头,只能通过URL参数传递认证信息:
在你的JwtAuthenticationFilter的doFilterInternal方法中,增加从请求参数获取token的逻辑:
String token = request.getHeader("Authorization"); // 新增以下逻辑 if (token == null) { token = request.getParameter("token"); } // 保留你原有token校验逻辑不变
- 前端发起SockJS连接时,在URL后拼接JWT令牌参数:
修改你的TS代码:
private socketFactory() { // 替换为你实际存储JWT令牌的位置 const jwtToken = localStorage.getItem('your_jwt_key'); return new SockJS(`https://localhost:8443/api/ws?token=${jwtToken}`); }
额外配置修正
你当前的控制器配置存在路径错误:你在WebSocketMessageConfig中配置了setApplicationDestinationPrefixes("/app"),所以@MessageMapping("/api/ws")对应的实际客户端消息推送路径是/app/api/ws,后续连接通了之后发消息需要注意路径匹配。
内容的提问来源于stack exchange,提问作者xectpp
相关产品推荐
相关产品推荐

