window.open添加身份验证头_Spring 5.2.2 WebSockets之STOMP的(简单和外部)代理、身份验证...

      接着Spring 5.2.2 WebSockets之STOMP的WebSocket服务端、信息流和注释的控制器继续讲STOMP。

8、简单代理

      内置的简单消息代理处理来自客户端的订阅请求,将它们存储在内存中,并将消息广播到具有匹配目的地的已连接客户端。代理支持类似路径的目的地,包括对Ant样式的目的地模式的订阅。

      如果配置了任务定时器,那么简单代理支持STOMP心跳。为此,你可以声明自己的定时任务程序,也可以使用自动声明并在内部使用的定时任务程序。以下示例显示如何声明自己的计划程序:

@Configuration@EnableWebSocketMessageBrokerpublic class WebSocketConfig implements WebSocketMessageBrokerConfigurer {    private TaskScheduler messageBrokerTaskScheduler;    @Autowired    public void setMessageBrokerTaskScheduler(TaskScheduler taskScheduler) {        this.messageBrokerTaskScheduler = taskScheduler;    }    @Override    public void configureMessageBroker(MessageBrokerRegistry registry) {        registry.enableSimpleBroker("/queue/", "/topic/")                .setHeartbeatValue(new long[] {10000, 20000})                .setTaskScheduler(this.messageBrokerTaskScheduler);        // ...    }}

9、外部代理

      简单代理非常适合入门,但只支持STOMP命令的一个子集(它不支持ack、receipts和其他一些特性),依赖于一个简单的消息发送循环,不适合集群。另一种选择是,你可以升级应用程序以使用功能齐全的message  broker。

     请参阅所选消息代理(如RabbitMQ、ActiveMQ等)的STOMP文档,安装代理,并在启用STOMP支持的情况下运行它。然后可以在Spring配置中启用STOMP代理转发(而不是简单代理)。

下面的示例配置启用功能齐全的代理:

@Configuration@EnableWebSocketMessageBrokerpublic class WebSocketConfig implements WebSocketMessageBrokerConfigurer {    @Override    public void registerStompEndpoints(StompEndpointRegistry registry) {        registry.addEndpoint("/portfolio").withSockJS();    }    @Override    public void configureMessageBroker(MessageBrokerRegistry registry) {        registry.enableStompBrokerRelay("/topic", "/queue");        registry.setApplicationDestinationPrefixes("/app");    }}

以下示例显示了与前一个示例等效的XML配置:

<beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:websocket="http://www.springframework.org/schema/websocket"    xsi:schemaLocation="        http://www.springframework.org/schema/beans        https://www.springframework.org/schema/beans/spring-beans.xsd        http://www.springframework.org/schema/websocket        https://www.springframework.org/schema/websocket/spring-websocket.xsd">    <websocket:message-broker application-destination-prefix="/app">        <websocket:stomp-endpoint path="/portfolio" />            <websocket:sockjs/>        websocket:stomp-endpoint>        <websocket:stomp-broker-relay prefix="/topic,/queue" />    websocket:message-broker>beans>

     前面配置中的stomp broker转发是一个spring MessageHandler,它通过将消息转发到外部消息代理来处理消息。为此,它建立到代理的TCP连接,将所有消息转发给它,然后通过WebSocket会话将从代理接收到的所有消息转发给客户端。本质上,它充当一个双向转发消息的“中继”。

     添加io.projectreactor.netty:reactor-netty和io.netty:netty-all依赖项以进行TCP连接管理。

      此外,应用程序组件(如HTTP请求处理方法、业务服务等)也可以向代理中继发送消息,如发送消息中所述,向订阅的WebSocket客户端广播消息。实际上,代理中继支持健壮和可伸缩的消息广播。

10、连接代理

      STOMP代理中继维护与代理的单个“系统”TCP连接。此连接仅用于来自服务器端应用程序的消息,不用于接收消息。你可以连接配置STOMP凭据(即STOMP frame  login 和passcode  headers)。这在XML命名空间和Java配置中都作为默认值guest 和guest 的systemLogin和systemPasscode 属性公开。

     STOMP代理转发还为每个连接的WebSocket客户端创建单独的TCP连接。可以配置用于代表客户端创建的所有TCP连接的STOMP凭据。这在XML命名空间和Java配置中都作为clientLogin 和`clientPasscode 属性公开,默认值为guest和`guest。

      stomp broker中继总是在它代表客户端转发给代理的每个CONNECT frame上设置login 和passcode headers。因此,WebSocket客户端不需要设置这些headers。它们被忽略了。正如身份验证部分所解释的,WebSocket客户端应该依赖HTTP身份验证来保护WebSocket端点并建立客户端标识。

     stomp  broker中继还通过“system”TCP连接向message  broker发送和接收心跳信号。可以配置发送和接收心跳信号的间隔(默认情况下每个间隔10秒)。如果与代理的连接丢失,代理中继每隔5秒继续尝试重新连接,直到成功。

     任何Spring bean都可以实现ApplicationListener在与代理的“system”连接丢失和重新建立时接收通知。例如,当没有活动的“system”连接时, Stock Quote的stock quotes服务可以停止尝试发送消息。

    默认情况下,STOMP代理中继始终连接到同一主机和端口,并在连接丢失时根据需要重新连接。如果希望提供多个地址,则每次尝试连接时,可以配置地址供应商,而不是固定主机和端口。下面的示例演示如何执行此操作:

@Configuration@EnableWebSocketMessageBrokerpublic class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {    // ...    @Override    public void configureMessageBroker(MessageBrokerRegistry registry) {        registry.enableStompBrokerRelay("/queue/", "/topic/").setTcpClient(createTcpClient());        registry.setApplicationDestinationPrefixes("/app");    }    private ReactorNettyTcpClient<byte[]> createTcpClient() {        return new ReactorNettyTcpClient<>(                client -> client.addressSupplier(() -> ... ),                new StompReactorNettyCodec());    }}

     还可以使用virtualHost 属性配置STOMP代理中继。此属性的值被设置为每个CONNECT frame的host 头,并且可能很有用(例如,在建立TCP连接的实际主机与提供基于云的STOMP服务的主机不同的云环境中)。

11、点作为分隔符

       当消息路由到@MessageMapping方法时,它们将与AntPathMatcher匹配。默认情况下,模式应该使用斜杠 (/)作为分隔符。这是web应用程序中的一个很好的规定,类似于httpurl。但是,如果你更习惯于消息传递规定,可以切换到使用点(.)作为分隔符。

下面的示例演示如何在Java配置中执行此操作:

@Configuration@EnableWebSocketMessageBrokerpublic class WebSocketConfig implements WebSocketMessageBrokerConfigurer {    // ...    @Override    public void configureMessageBroker(MessageBrokerRegistry registry) {        registry.setPathMatcher(new AntPathMatcher("."));        registry.enableStompBrokerRelay("/queue", "/topic");        registry.setApplicationDestinationPrefixes("/app");    }}

以下示例显示了与前一个示例等效的XML配置:

<beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xmlns:websocket="http://www.springframework.org/schema/websocket"        xsi:schemaLocation="                http://www.springframework.org/schema/beans                https://www.springframework.org/schema/beans/spring-beans.xsd                http://www.springframework.org/schema/websocket                https://www.springframework.org/schema/websocket/spring-websocket.xsd">    <websocket:message-broker application-destination-prefix="/app" path-matcher="pathMatcher">        <websocket:stomp-endpoint path="/stomp"/>        <websocket:stomp-broker-relay prefix="/topic,/queue" />    websocket:message-broker>    <bean id="pathMatcher" class="org.springframework.util.AntPathMatcher">        <constructor-arg index="0" value="."/>    bean>beans>

之后,控制器可以在@MessageMapping方法中使用点(.)作为分隔符,如下例所示:

@Controller@MessageMapping("red")public class RedController {    @MessageMapping("blue.{green}")    public void handleGreen(@DestinationVariable String green) {        // ...    }}

客户端发送消息/app/red.blue.green123.

      在前面的示例中,我们没有更改“代理中继”上的前缀,因为这些前缀完全依赖于外部消息代理。另一方面,“简单代理”确实依赖于配置的PathMatcher,因此,如果你切换分隔符,也适用于代理以及代理将目标从消息匹配到订阅模式的方式。

12、身份验证

      每个stomp  over  websocket消息传递会话都从一个HTTP请求开始。这可以是升级到WebSockets的请求(即WebSocket握手),或者,在SockJS回退的情况下,是一系列SockJS HTTP传输请求。

     许多web应用程序已经有了身份验证和授权来保护HTTP请求。通常,用户通过Spring Security某种机制进行身份验证,比如登录页面、HTTP基本身份验证或其他方式。已验证用户的安全上下文保存在HTTP会话中,并与同一基于cookie的会话中的后续请求相关联。

     因此,对于WebSocket握手或SockJS HTTP传输请求,通常已经有一个经过身份验证的用户可以通过HttpServletRequest#getUserPrincipal()进行访问。Spring会自动将该用户与为其创建的WebSocket或SockJS会话相关联,并且随后与通过用户头在该会话上传输的所有STOMP消息相关联。

    简言之,一个典型的web应用程序只需要做它已经做的安全工作。通过基于cookie的HTTP会话(然后与为该用户创建的WebSocket或SockJS会话关联)维护的安全上下文在HTTP请求级别对用户进行身份验证,并在流经应用程序的每个Message 上生成一个用户headers 。

    请注意,STOMP协议在CONNECT 帧上确实有login 和passcode headers 。它们最初是为TCP上的STOMP而设计的,现在仍然需要。但是,对于STOMP over WebSocket,默认情况下,Spring忽略STOMP协议级别的授权headers ,假设用户已经在HTTP传输级别进行了身份验证,并期望WebSocket或SockJS会话包含经过身份验证的用户。

     Spring Security提供WebSocket子协议授权,它使用ChannelInterceptor 根据消息中的用户headers 对消息进行授权。另外,Spring Session提供了一个WebSocket集成,确保当WebSocket会话仍然处于活动状态时,用户HTTP会话不会过期。

STOMP未完待续!

敬请持续关注。

欢迎关注和转发Spring中文社区(加微信群,可以关注后加我微信):

0c7935830303232a3f0347b032fc4952.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值