SpringWebSockets:特定のユーザーにメッセージを送信する
1. 序章
このチュートリアルでは、を使用してSpring WebSocketを使用して1人のユーザーにSTOMPメッセージを送信する方法について説明します。すべてのメッセージをすべてのユーザーにブロードキャストしたくない場合があるため、これは重要です。 さらに、これらのメッセージを安全な方法で送信する方法を示します。
WebSocketの概要については、thisの優れたチュートリアルで起動して実行する方法を確認してください。 また、セキュリティの詳細については、このの記事をチェックして、WebSocketの実装を保護してください。
2. キュー、トピック、およびエンドポイント
Spring WebSocketとSTOMPを使用して、メッセージの送信先とメッセージのサブスクライブ方法を
- トピック–任意のクライアントまたはユーザーが利用できる一般的な会話またはチャットトピック
- キュー–特定のユーザーとその現在のセッション用に予約済み
- エンドポイント–汎用エンドポイント
次に、それぞれのコンテキストパスの例を簡単に見てみましょう。
- 「/topic/movies」
- 「/user/ queue/specific-user」
- 「/secured/chat」
トピックとエンドポイントはこの機能をサポートしていないため、特定のユーザーにメッセージを送信するにはキューを使用する必要があることに注意してください。
3. 構成
次に、特定のユーザーにメッセージを送信できるようにアプリケーションを構成する方法を学びましょう。
public class SocketBrokerConfig extends
AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/secured/user/queue/specific-user");
config.setApplicationDestinationPrefixes("/spring-security-mvc-socket");
config.setUserDestinationPrefix("/secured/user");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/secured/room").withSockJS();
}
}
どのエンドポイントがシングルユーザー用に予約されているかを決定するので、ユーザーの宛先を含めるようにしてください。
また、すべてのキューとユーザーの宛先に「/ secureed」のプレフィックスを付けて、認証が必要になるようにします。 保護されていないエンドポイントの場合、「/ secureed」プレフィックスを削除できます(他のセキュリティ設定の結果として)。
pom.xml の観点からは、追加の依存関係は必要ありません。
4. URLマッピング
次のパターンに準拠するURLマッピングを使用して、クライアントがキューにサブスクライブするようにします。
"/user/queue/updates"
このマッピングは、UserDestinationMessageHandlerによってユーザーセッション固有のアドレスに自動的に変換されます。
たとえば、“ user123” という名前のユーザーがいる場合、対応するアドレスは次のようになります。
"/queue/updates-user123"
サーバー側では、次のURLマッピングパターンを使用してユーザー固有の応答を送信します。
"/user/{username}/queue/updates"
これも、クライアント側で既にサブスクライブしている正しいURLマッピングに変換されます。
したがって、ここでの必須成分は2つあることがわかります:
- 指定したユーザー宛先プレフィックス( AbstractWebSocketMessageBrokerConfigurer で構成)を付加します。
- マッピング内のどこかで「/queue」を使用します。
次のセクションでは、これを行う方法を正確に見ていきます。
5. convertAndSendToUser()を呼び出す
SimpmessagingTemplateまたはSimpMessageSendingOperationsからconvertAndSendToUser()を非静的に呼び出すことができます。
@Autowired
private SimpMessagingTemplate simpMessagingTemplate;
@MessageMapping("/secured/room")
public void sendSpecific(
@Payload Message msg,
Principal user,
@Header("simpSessionId") String sessionId) throws Exception {
OutputMessage out = new OutputMessage(
msg.getFrom(),
msg.getText(),
new SimpleDateFormat("HH:mm").format(new Date()));
simpMessagingTemplate.convertAndSendToUser(
msg.getTo(), "/secured/user/queue/specific-user", out);
}
お気づきかもしれません:
@Header("simpSessionId") String sessionId
@Headerアノテーションにより、インバウンドメッセージによって公開されたヘッダーにアクセスできます。たとえば、複雑なインターセプターを必要とせずに、現在のsessionIdを取得できます。 同様に、プリンシパルを介して現在のユーザーにアクセスできます。
重要なのは、この記事で採用しているアプローチにより、URLマッピングに関して@sendToUserアノテーションをさらにカスタマイズできることです。 そのアノテーションの詳細については、thisのすばらしい記事をご覧ください。
クライアント側では、JavaScriptで connect()を使用して SockJSインスタンスを初期化し、STOMP:を使用してWebSocketサーバーに接続します。
var socket = new SockJS('/secured/room');
var stompClient = Stomp.over(socket);
var sessionId = "";
stompClient.connect({}, function (frame) {
var url = stompClient.ws._transport.url;
url = url.replace(
"ws://localhost:8080/spring-security-mvc-socket/secured/room/", "");
url = url.replace("/websocket", "");
url = url.replace(/^[0-9]+\//, "");
console.log("Your current session is: " + url);
sessionId = url;
}
また、提供された sessionId にアクセスし、それを「 secure/room」URLマッピングに追加します。 これにより、ユーザー固有のサブスクリプションキューを動的かつ手動で提供できるようになります:
stompClient.subscribe('secured/user/queue/specific-user'
+ '-user' + that.sessionId, function (msgOut) {
//handle messages
}
すべてが設定されると、次のように表示されます。
そして私たちのサーバーコンソールで:
6. 結論
このトピックの詳細については、Springの公式ブログおよび公式ドキュメントを確認してください。
いつものように、この記事で使用されているコードサンプルは、GitHubでから入手できます。