染指余忆 2024-04-23 21:38 采纳率: 96.3%
浏览 18
已结题

springboot websocket添加httpsession认证和拦截器

springboot websocket添加httpsession认证和拦截器,WebMvcConfigurer,addInterceptors(InterceptorRegistry registry)对websocket无效拦截

@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        WebMvcConfigurer.super.addInterceptors(registry);
        registry.addInterceptor(new Handler_test()).addPathPatterns("/**");
    }
}
public class HandlerWebSocket implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println(request.getSession().getId());
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

  • 写回答

5条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-23 21:38
    关注

    引自免费微信小程序:皆我百晓生

    在Spring Boot中,如果你想要在WebSocket会话中实现HTTP Session认证和拦截,你需要处理WebSocket特定的生命周期方法,并且不是通过WebMvcConfigurer和拦截器(HandlerInterceptor)来完成的。因为WebSocket连接并不依赖于HTTP请求/响应模型,所以传统的MVC拦截器不适用于WebSocket。

    为了解决这个问题,你可以创建一个自定义的TextWebSocketHandler子类并实现认证逻辑。这里是一个详细的步骤和示例代码:

    1. 首先,创建一个自定义的WebSocket处理器:
    import org.springframework.messaging.handler.annotation.MessageMapping;
    import org.springframework.stereotype.Component;
    import org.springframework.web.socket.TextMessage;
    import org.springframework.web.socket.WebSocketSession;
    
    @Component
    public class SecureWebSocketHandler extends TextWebSocketHandler {
    
        private static final Logger logger = LoggerFactory.getLogger(SecureWebSocketHandler.class);
    
        @Override
        public void afterConnectionEstablished(WebSocketSession session) throws Exception {
            String sessionId = (String) session.getHandshakeAttributes().get(HttpHeaders.SESSION_ID);
            HttpSession httpSession = getSessionFromHttpRequest(sessionId);
    
            if (httpSession == null || !isUserAuthenticated(httpSession)) {
                logger.warn("Closing unauthenticated WebSocket connection: {}", session.getId());
                session.close();
                return;
            }
    
            super.afterConnectionEstablished(session);
        }
    
        // Implement your logic to get the HTTP session from the given session ID
        private HttpSession getSessionFromHttpRequest(String sessionId) {
            // Here you can use a custom method or library like Spring Security's 
            // HttpSessionStrategy to retrieve the HTTP session based on the session ID.
            // For simplicity, let's assume we have a direct access to the sessions map:
            Map<String, HttpSession> sessionsMap = ...; // Replace with your implementation
            return sessionsMap.get(sessionId);
        }
    
        // Implement your logic to check if the user is authenticated in the HTTP session
        private boolean isUserAuthenticated(HttpSession httpSession) {
            // For example, if using Spring Security, you could do:
            // Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            // return authentication != null && !authentication.getName().equals("anonymousUser");
    
            // For simplicity, let's assume that any non-null session means the user is authenticated
            return httpSession != null;
        }
    
        @Override
        protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
            // Your business logic here
            logger.info("Received message: {}", message.getPayload());
            session.sendMessage(new TextMessage("Echo: " + message.getPayload()));
        }
    }
    
    1. 在配置文件中启用WebSocket支持:
    import org.springframework.context.annotation.Configuration;
    import org.springframework.messaging.simp.config.MessageBrokerRegistry;
    import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
    import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
    import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
    
    @Configuration
    @EnableWebSocketMessageBroker
    public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    
        @Override
        public void configureMessageBroker(MessageBrokerRegistry config) {
            config.enableSimpleBroker("/topic");
            config.setApplicationDestinationPrefixes("/app");
        }
    
        @Override
        public void registerStompEndpoints(StompEndpointRegistry registry) {
            registry.addEndpoint("/ws").withSockJS();
        }
    }
    
    1. 为了处理客户端的连接请求,你可能还需要一个简单的控制器:
    import org.springframework.messaging.handler.annotation.MessageMapping;
    import org.springframework.messaging.handler.annotation.SendTo;
    import org.springframework.web.bind.annotation.Controller;
    
    @Controller
    public class WebSocketController {
    
        @MessageMapping("/connect")
        @SendTo("/topic/messages")
        public String connect(String message) {
            return "Connected: " + message;
        }
    }
    

    这样,每次新的WebSocket连接建立时,都会调用SecureWebSocketHandler中的afterConnectionEstablished()方法进行认证。如果用户未通过认证,将关闭WebSocket连接。

    注意:这个例子没有包含具体的HTTP Session获取逻辑,你需要根据你的应用环境(例如是否使用Spring Security等)来实现这部分功能。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(4条)

报告相同问题?

问题事件

  • 系统已结题 9月18日
  • 已采纳回答 9月10日
  • 创建了问题 4月23日

悬赏问题

  • ¥15 12864只亮屏 不显示汉字
  • ¥20 三极管1000倍放大电路
  • ¥15 vscode报错如何解决
  • ¥15 前端vue CryptoJS Aes CBC加密后端java解密
  • ¥15 python随机森林对两个excel表格读取,shap报错
  • ¥15 基于STM32心率血氧监测(OLED显示)相关代码运行成功后烧录成功OLED显示屏不显示的原因是什么
  • ¥100 X轴为分离变量(因子变量),如何控制X轴每个分类变量的长度。
  • ¥30 求给定范围的全体素数p的(p-2)/p的连乘积值
  • ¥15 VFP如何使用阿里TTS实现文字转语音?
  • ¥100 需要跳转番茄畅听app的adb命令