package com.github.paicoding.forum.web.front.chat.stomp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.server.HandshakeHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
/**
* v1.1 stomp协议的websocket实现的chatgpt聊天方式
*
* @author YiHui
* @date 2023/6/5
*/
@Slf4j
@Configuration
@EnableWebSocketMessageBroker // 开启websocket代理
public class WsChatConfig implements WebSocketMessageBrokerConfigurer {
/**
* 这里定义的是客户端接收服务端消息的相关信息,如派聪明的回答: WsAnswerHelper#response 就是往 "/chat/rsp" 发送消息
* 对应的前端订阅的也是 chat/index.html: stompClient.subscribe(`/user/chat/rsp`, xxx)
*
* @param config
*/
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
// 开启一个简单的基于内存的消息代理,前缀是/user的将消息会转发给消息代理 broker
// 然后再由消息代理,将消息广播给当前连接的客户端
config.enableSimpleBroker("/chat");
// 表示配置一个或多个前缀,通过这些前缀过滤出需要被注解方法处理的消息。
// 例如,前缀为 /app 的 destination 可以通过@MessageMapping注解的方法处理,
// 而其他 destination (例如 /topic /queue)将被直接交给 broker 处理
config.setApplicationDestinationPrefixes("/app");
}
/**
* 添加一个服务端点,来接收客户端的连接
* 即客户端创建ws时,指定的地址, chat/index.html: let socket = new WebSocket(`${protocol}//${host}/gpt/${session}/${aiType}`);
* @param registry
*/
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// 注册一个 /gpt/{id} 的 WebSocket endPoint; 其中 {id} 用于让用户连接终端时都可以有自己的路径
// 作为 Principal 的标识,以便实现向指定用户发送信息
// sockjs 可以解决浏览器对 WebSocket 的兼容性问题,
registry.addEndpoint("/gpt/{id}/{aiType}")
.setHandshakeHandler(new AuthHandshakeHandler())
.addInterceptors(new AuthHandshakeInterceptor())
// 注意下面这个,不要使用 setAllowedOrigins("*"),使用之后有啥问题可以实操验证一下🐕
// setAllowedOrigins接受一个字符串数组作为参数,每个元素代表一个允许访问的客户端地址,内部的值为具体的 "http://localhost:8080"
// setAllowedOriginPatterns接受一个正则表达式数组作为参数,每个元素代表一个允许访问的客户端地址的模式, 内部值可以为正则,如 "*", "http://*:8080"
.setAllowedOriginPatterns("*")
;
}
/**
* 配置接收消息的拦截器
*
* @param registration
*/
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(channelInInterceptor());
}
/**
* 配置返回消息的拦截器
*
* @param registration
*/
@Override
public void configureClientOutboundChannel(ChannelRegistration registration) {
registration.interceptors(channelOutInterceptor());
}
@Bean
public HandshakeHandler handshakeHandler() {
return new AuthHandshakeHandler();
}
@Bean
public HttpSessionHandshakeInterceptor handshakeInterceptor() {
return new AuthHandshakeInterceptor();
}
@Bean
public ChannelInterceptor channelInInterceptor() {
return new AuthInChannelInterceptor();
}
@Bean
public ChannelInterceptor channelOutInterceptor() {
return new AuthOutChannelInterceptor();
}
}
这段代码是一个Spring配置类WsChatConfig
,基于STOMP协议的WebSocket消息代理和相关的安全握手处理器以及消息拦截器。这个类通过实现WebSocketMessageBrokerConfigurer
接口来定义WebSocket通信的路由、安全握手以及消息拦截的逻辑。
核心方法详解
-
configureMessageBroker(MessageBrokerRegistry config):
- 此方法用于配置消息代理的行为。
-
enableSimpleBroker
方法开启了一个基于内存的消息代理,所有以/chat
为前缀的消息都会被转发到这个代理。 -
setApplicationDestinationPrefixes
方法设置了应用前缀,这意味着所有以/app
为前缀的目的地(destination)都可以通过注解方法进行处理。
-
registerStompEndpoints(StompEndpointRegistry registry):
- 此方法用于注册WebSocket端点,客户端将连接到这些端点。
-
addEndpoint
方法注册了一个端点/gpt/{id}/{aiType}
,其中{id}
和{aiType}
是路径变量,可以用于区分不同的用户和AI类型。 -
setHandshakeHandler
方法设置了自定义的握手处理器AuthHandshakeHandler
,用于在握手阶段进行安全验证。 -
addInterceptors
方法添加了自定义的握手拦截器AuthHandshakeInterceptor
,用于在握手过程中进行额外的处理。 -
setAllowedOriginPatterns
方法设置了允许连接的客户端地址模式,这里使用了通配符*
表示允许所有地址。
-
configureClientInboundChannel(ChannelRegistration registration):
- 此方法配置了客户端接收消息的通道,并设置了拦截器
AuthInChannelInterceptor
,用于在消息发送前进行权限验证。
- 此方法配置了客户端接收消息的通道,并设置了拦截器
-
configureClientOutboundChannel(ChannelRegistration registration):
- 此方法配置了客户端发送消息的通道,并设置了拦截器
AuthOutChannelInterceptor
,用于在消息接收后进行处理。
- 此方法配置了客户端发送消息的通道,并设置了拦截器
-
handshakeHandler(), handshakeInterceptor(), channelInInterceptor(), channelOutInterceptor():
- 这些方法分别创建了对应的Bean实例,它们在配置方法中被引用。
使用场景
WsChatConfig
类适用于需要实现基于STOMP协议的WebSocket聊天应用的场景。它通过配置消息代理和安全握手处理器,确保了消息的安全传输和用户的认证。文章来源:https://www.toymoban.com/news/detail-858268.html
注意事项
- 配置中的
setAllowedOriginPatterns("*")
允许所有地址访问WebSocket端点,这在生产环境中是不推荐的,因为它可能导致安全风险。在生产环境中,应该将其替换为具体的客户端地址或者正则表达式模式。 - 路径变量
{id}
和{aiType}
需要在握手处理器或拦截器中进行相应的处理,以确保消息可以正确地发送给指定的用户。 - 拦截器的使用应该根据实际的安全需求进行定制,例如,可以添加更多的权限验证逻辑来保护WebSocket通信。
- 配置类中的
@Bean
注解方法使得Spring容器能够管理这些处理器和拦截器的生命周期,确保它们在应用启动时被正确初始化。
WsChatConfig
类为基于STOMP协议的WebSocket聊天应用提供了一个全面的配置方案,包括消息代理的设置、安全握手的处理以及消息的拦截和验证。文章来源地址https://www.toymoban.com/news/detail-858268.html
到了这里,关于基于STOMP协议的WebSocket消息代理和相关的安全握手处理器以及消息拦截器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!