Skip to content

Commit 4e5e700

Browse files
committed
Add client login/passcode to broker relay
Issue: SPR-11154
1 parent 0a12f28 commit 4e5e700

File tree

8 files changed

+265
-42
lines changed

8 files changed

+265
-42
lines changed

spring-messaging/src/main/java/org/springframework/messaging/simp/config/StompBrokerRelayRegistration.java

+54-15
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,13 @@ public class StompBrokerRelayRegistration extends AbstractBrokerRegistration {
3333

3434
private int relayPort = 61613;
3535

36-
private String applicationLogin = "guest";
36+
private String clientLogin = "guest";
3737

38-
private String applicationPasscode = "guest";
38+
private String clientPasscode = "guest";
39+
40+
private String systemLogin = "guest";
41+
42+
private String systemPasscode = "guest";
3943

4044
private Long systemHeartbeatSendInterval;
4145

@@ -68,23 +72,54 @@ public StompBrokerRelayRegistration setRelayPort(int relayPort) {
6872
return this;
6973
}
7074

75+
7176
/**
72-
* Set the login for the "system" relay session used to send messages to the STOMP
73-
* broker without having a client session (e.g. REST/HTTP request handling method).
77+
* Set the login to use when creating connections to the STOMP broker on
78+
* behalf of connected clients.
79+
* <p>
80+
* By default this is set to "guest".
7481
*/
75-
public StompBrokerRelayRegistration setApplicationLogin(String login) {
76-
Assert.hasText(login, "applicationLogin must not be empty");
77-
this.applicationLogin = login;
82+
public StompBrokerRelayRegistration setClientLogin(String login) {
83+
Assert.hasText(login, "clientLogin must not be empty");
84+
this.clientLogin = login;
7885
return this;
7986
}
8087

8188
/**
82-
* Set the passcode for the "system" relay session used to send messages to the STOMP
83-
* broker without having a client session (e.g. REST/HTTP request handling method).
89+
* Set the passcode to use when creating connections to the STOMP broker on
90+
* behalf of connected clients.
91+
* <p>
92+
* By default this is set to "guest".
8493
*/
85-
public StompBrokerRelayRegistration setApplicationPasscode(String passcode) {
86-
Assert.hasText(passcode, "applicationPasscode must not be empty");
87-
this.applicationPasscode = passcode;
94+
public StompBrokerRelayRegistration setClientPasscode(String passcode) {
95+
Assert.hasText(passcode, "clientPasscode must not be empty");
96+
this.clientPasscode = passcode;
97+
return this;
98+
}
99+
100+
/**
101+
* Set the login for the shared "system" connection used to send messages to
102+
* the STOMP broker from within the application, i.e. messages not associated
103+
* with a specific client session (e.g. REST/HTTP request handling method).
104+
* <p>
105+
* By default this is set to "guest".
106+
*/
107+
public StompBrokerRelayRegistration setSystemLogin(String login) {
108+
Assert.hasText(login, "systemLogin must not be empty");
109+
this.systemLogin = login;
110+
return this;
111+
}
112+
113+
/**
114+
* Set the passcode for the shared "system" connection used to send messages to
115+
* the STOMP broker from within the application, i.e. messages not associated
116+
* with a specific client session (e.g. REST/HTTP request handling method).
117+
* <p>
118+
* By default this is set to "guest".
119+
*/
120+
public StompBrokerRelayRegistration setSystemPasscode(String passcode) {
121+
Assert.hasText(passcode, "systemPasscode must not be empty");
122+
this.systemPasscode = passcode;
88123
return this;
89124
}
90125

@@ -129,18 +164,22 @@ protected StompBrokerRelayMessageHandler getMessageHandler(SubscribableChannel b
129164

130165
handler.setRelayHost(this.relayHost);
131166
handler.setRelayPort(this.relayPort);
132-
handler.setSystemLogin(this.applicationLogin);
133-
handler.setSystemPasscode(this.applicationPasscode);
167+
168+
handler.setClientLogin(this.clientLogin);
169+
handler.setClientPasscode(this.clientPasscode);
170+
171+
handler.setSystemLogin(this.systemLogin);
172+
handler.setSystemPasscode(this.systemPasscode);
134173

135174
if (this.systemHeartbeatSendInterval != null) {
136175
handler.setSystemHeartbeatSendInterval(this.systemHeartbeatSendInterval);
137176
}
138-
139177
if (this.systemHeartbeatReceiveInterval != null) {
140178
handler.setSystemHeartbeatReceiveInterval(this.systemHeartbeatReceiveInterval);
141179
}
142180

143181
handler.setAutoStartup(this.autoStartup);
182+
144183
return handler;
145184
}
146185

spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandler.java

+70-16
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import org.springframework.messaging.tcp.TcpConnection;
3434
import org.springframework.messaging.tcp.TcpConnectionHandler;
3535
import org.springframework.messaging.tcp.TcpOperations;
36-
import org.springframework.messaging.tcp.reactor.ReactorNettyTcpClient;
3736
import org.springframework.util.Assert;
3837
import org.springframework.util.concurrent.ListenableFuture;
3938
import org.springframework.util.concurrent.ListenableFutureCallback;
@@ -51,13 +50,16 @@
5150
*
5251
* <p>This class also automatically opens a default "system" TCP connection to the message
5352
* broker that is used for sending messages that originate from the server application (as
54-
* opposed to from a client). Such messages are recognized because they are not associated
55-
* with any client and therefore do not have a session id header. The "system" connection
56-
* is effectively shared and cannot be used to receive messages. Several properties are
57-
* provided to configure the "system" connection including the the
58-
* {@link #setSystemLogin(String) login} {@link #setSystemPasscode(String) passcode},
59-
* heartbeat {@link #setSystemHeartbeatSendInterval(long) send} and
60-
* {@link #setSystemHeartbeatReceiveInterval(long) receive} intervals.
53+
* opposed to from a client). Such messages are are not associated with any client and
54+
* therefore do not have a session id header. The "system" connection is effectively
55+
* shared and cannot be used to receive messages. Several properties are provided to
56+
* configure the "system" connection including:
57+
* <ul>
58+
* <li>{@link #setSystemLogin(String)}</li>
59+
* <li>{@link #setSystemPasscode(String)}</li>
60+
* <li>{@link #setSystemHeartbeatSendInterval(long)}</li>
61+
* <li>{@link #setSystemHeartbeatReceiveInterval(long)}</li>
62+
* </ul>
6163
*
6264
* @author Rossen Stoyanchev
6365
* @author Andy Wilkinson
@@ -87,6 +89,10 @@ public class StompBrokerRelayMessageHandler extends AbstractBrokerMessageHandler
8789

8890
private int relayPort = 61613;
8991

92+
private String clientLogin = "guest";
93+
94+
private String clientPasscode = "guest";
95+
9096
private String systemLogin = "guest";
9197

9298
private String systemPasscode = "guest";
@@ -198,33 +204,79 @@ public long getSystemHeartbeatReceiveInterval() {
198204
}
199205

200206
/**
201-
* Set the login for the "system" connection used to send messages to the STOMP
202-
* broker without having a client session (e.g. REST/HTTP request handling method).
203-
* <p>See class-level documentation for more information on the "system" connection.
207+
* Set the login to use when creating connections to the STOMP broker on
208+
* behalf of connected clients.
209+
* <p>
210+
* By default this is set to "guest".
211+
* @see #setSystemLogin(String)
212+
*/
213+
public void setClientLogin(String clientLogin) {
214+
Assert.hasText(clientLogin, "clientLogin must not be empty");
215+
this.clientLogin = clientLogin;
216+
}
217+
218+
/**
219+
* @return the configured login to use for connections to the STOMP broker
220+
* on behalf of connected clients.
221+
* @see #getSystemLogin()
222+
*/
223+
public String getClientLogin() {
224+
return this.clientLogin;
225+
}
226+
227+
/**
228+
* Set the clientPasscode to use to create connections to the STOMP broker on
229+
* behalf of connected clients.
230+
* <p>
231+
* By default this is set to "guest".
232+
* @see #setSystemPasscode(String)
233+
*/
234+
public void setClientPasscode(String clientPasscode) {
235+
Assert.hasText(clientPasscode, "clientPasscode must not be empty");
236+
this.clientPasscode = clientPasscode;
237+
}
238+
239+
/**
240+
* @return the configured passocde to use for connections to the STOMP broker on
241+
* behalf of connected clients.
242+
* @see #getSystemPasscode()
243+
*/
244+
public String getClientPasscode() {
245+
return this.clientPasscode;
246+
}
247+
248+
/**
249+
* Set the login for the shared "system" connection used to send messages to
250+
* the STOMP broker from within the application, i.e. messages not associated
251+
* with a specific client session (e.g. REST/HTTP request handling method).
252+
* <p>
253+
* By default this is set to "guest".
204254
*/
205255
public void setSystemLogin(String systemLogin) {
206256
Assert.hasText(systemLogin, "systemLogin must not be empty");
207257
this.systemLogin = systemLogin;
208258
}
209259

210260
/**
211-
* @return the login used by the "system" connection to connect to the STOMP broker
261+
* @return the login used for the shared "system" connection to the STOMP broker
212262
*/
213263
public String getSystemLogin() {
214264
return this.systemLogin;
215265
}
216266

217267
/**
218-
* Set the passcode for the "system" connection used to send messages to the STOMP
219-
* broker without having a client session (e.g. REST/HTTP request handling method).
220-
* <p>See class-level documentation for more information on the "system" connection.
268+
* Set the passcode for the shared "system" connection used to send messages to
269+
* the STOMP broker from within the application, i.e. messages not associated
270+
* with a specific client session (e.g. REST/HTTP request handling method).
271+
* <p>
272+
* By default this is set to "guest".
221273
*/
222274
public void setSystemPasscode(String systemPasscode) {
223275
this.systemPasscode = systemPasscode;
224276
}
225277

226278
/**
227-
* @return the passcode used by the "system" connection to connect to the STOMP broker
279+
* @return the passcode used for the shared "system" connection to the STOMP broker
228280
*/
229281
public String getSystemPasscode() {
230282
return this.systemPasscode;
@@ -348,6 +400,8 @@ protected void handleMessageInternal(Message<?> message) {
348400

349401
if (SimpMessageType.CONNECT.equals(messageType)) {
350402
logger.debug("Processing CONNECT in session=" + sessionId);
403+
headers.setLogin(this.clientLogin);
404+
headers.setPasscode(this.clientPasscode);
351405
if (getVirtualHost() != null) {
352406
headers.setHost(getVirtualHost());
353407
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright 2002-2013 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.messaging.simp.config;
18+
19+
import org.junit.Before;
20+
import org.junit.Test;
21+
import org.springframework.messaging.MessageChannel;
22+
import org.springframework.messaging.StubMessageChannel;
23+
import org.springframework.messaging.SubscribableChannel;
24+
import org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler;
25+
26+
import java.util.Arrays;
27+
28+
import static org.junit.Assert.assertArrayEquals;
29+
import static org.junit.Assert.assertEquals;
30+
31+
/**
32+
* Unit tests for {@link org.springframework.messaging.simp.config.StompBrokerRelayRegistration}.
33+
*
34+
* @author Rossen Stoyanchev
35+
*/
36+
public class StompBrokerRelayRegistrationTests {
37+
38+
39+
@Test
40+
public void test() {
41+
42+
SubscribableChannel clientInboundChannel = new StubMessageChannel();
43+
MessageChannel clientOutboundChannel = new StubMessageChannel();
44+
SubscribableChannel brokerChannel = new StubMessageChannel();
45+
46+
String[] destinationPrefixes = new String[] { "/foo", "/bar" };
47+
48+
StompBrokerRelayRegistration registration = new StompBrokerRelayRegistration(
49+
clientInboundChannel, clientOutboundChannel, destinationPrefixes);
50+
51+
registration.setClientLogin("clientlogin");
52+
registration.setClientPasscode("clientpasscode");
53+
registration.setSystemLogin("syslogin");
54+
registration.setSystemPasscode("syspasscode");
55+
registration.setSystemHeartbeatReceiveInterval(123);
56+
registration.setSystemHeartbeatSendInterval(456);
57+
58+
StompBrokerRelayMessageHandler relayMessageHandler = registration.getMessageHandler(brokerChannel);
59+
60+
assertEquals(Arrays.asList(destinationPrefixes), relayMessageHandler.getDestinationPrefixes());
61+
assertEquals("clientlogin", relayMessageHandler.getClientLogin());
62+
assertEquals("clientpasscode", relayMessageHandler.getClientPasscode());
63+
assertEquals("syslogin", relayMessageHandler.getSystemLogin());
64+
assertEquals("syspasscode", relayMessageHandler.getSystemPasscode());
65+
assertEquals(123, relayMessageHandler.getSystemHeartbeatReceiveInterval());
66+
assertEquals(456, relayMessageHandler.getSystemHeartbeatSendInterval());
67+
}
68+
69+
}

spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandlerTests.java

+29-2
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,7 @@ public class StompBrokerRelayMessageHandlerTests {
5050

5151
@Before
5252
public void setup() {
53-
5453
this.tcpClient = new StubTcpOperations();
55-
5654
this.brokerRelay = new StompBrokerRelayMessageHandler(new StubMessageChannel(),
5755
new StubMessageChannel(), new StubMessageChannel(), Arrays.asList("/topic"));
5856
this.brokerRelay.setTcpClient(this.tcpClient);
@@ -83,6 +81,35 @@ public void testVirtualHostHeader() {
8381
assertEquals(virtualHost, headers2.getHost());
8482
}
8583

84+
@Test
85+
public void testLoginPasscode() {
86+
87+
String sessionId = "sess1";
88+
89+
StompHeaderAccessor headers = StompHeaderAccessor.create(StompCommand.CONNECT);
90+
headers.setSessionId(sessionId);
91+
92+
this.brokerRelay.setClientLogin("clientlogin");
93+
this.brokerRelay.setClientPasscode("clientpasscode");
94+
95+
this.brokerRelay.setSystemLogin("syslogin");
96+
this.brokerRelay.setSystemPasscode("syspasscode");
97+
98+
this.brokerRelay.start();
99+
this.brokerRelay.handleMessage(MessageBuilder.withPayload(new byte[0]).setHeaders(headers).build());
100+
101+
List<Message<byte[]>> sent = this.tcpClient.connection.messages;
102+
assertEquals(2, sent.size());
103+
104+
StompHeaderAccessor headers1 = StompHeaderAccessor.wrap(sent.get(0));
105+
assertEquals("syslogin", headers1.getLogin());
106+
assertEquals("syspasscode", headers1.getPasscode());
107+
108+
StompHeaderAccessor headers2 = StompHeaderAccessor.wrap(sent.get(1));
109+
assertEquals("clientlogin", headers2.getLogin());
110+
assertEquals("clientpasscode", headers2.getPasscode());
111+
}
112+
86113
@Test
87114
public void testDestinationExcluded() {
88115

spring-websocket/src/main/java/org/springframework/web/socket/config/MessageBrokerBeanDefinitionParser.java

+10-2
Original file line numberDiff line numberDiff line change
@@ -303,11 +303,19 @@ else if (brokerRelayElem != null) {
303303
if(!relayPort.isEmpty()) {
304304
mpvs.add("relayPort", Integer.valueOf(relayPort));
305305
}
306-
String attrValue = brokerRelayElem.getAttribute("login");
306+
String attrValue = brokerRelayElem.getAttribute("client-login");
307+
if(!attrValue.isEmpty()) {
308+
mpvs.add("clientLogin",attrValue);
309+
}
310+
attrValue = brokerRelayElem.getAttribute("client-passcode");
311+
if(!attrValue.isEmpty()) {
312+
mpvs.add("clientPasscode", attrValue);
313+
}
314+
attrValue = brokerRelayElem.getAttribute("system-login");
307315
if(!attrValue.isEmpty()) {
308316
mpvs.add("systemLogin",attrValue);
309317
}
310-
attrValue = brokerRelayElem.getAttribute("passcode");
318+
attrValue = brokerRelayElem.getAttribute("system-passcode");
311319
if(!attrValue.isEmpty()) {
312320
mpvs.add("systemPasscode", attrValue);
313321
}

0 commit comments

Comments
 (0)