Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Spring Boot integrates WebSocket and Spring Security instances

2025-01-22 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/03 Report--

One. Why do you need WebSocket

In HTTP protocol, all requests are initiated by the client and responded by the server, and the server cannot push messages to the client. But in some applications that require instant messaging, it is inevitable that the server pushes messages to the client. The traditional solutions are as follows

1. Polling

Polling is the simplest solution. Its significance lies in that the client keeps sending requests to the server at fixed time intervals to check whether the server has new data. If the server has new data, it returns it to the client. If the server has no new data, it returns an empty JSON or XML document. Polling is convenient for developers to implement. But the disadvantages are obvious: the client has to establish new HTTP requests every time, and the server has to deal with a large number of invalid requests, which will seriously slow down the efficiency of the server in high concurrency scenarios, and at the same time, the resources of the server are greatly wasted. Therefore, this approach is not desirable.

two。 Long polling

Long polling partially solves the problem of polling. In long polling, the server will not respond to the client immediately after receiving the client's request, but will wait until the server has new data to respond to the client's request immediately. Otherwise, the server will hold the request and will not return until there is new data, which saves the server's resources to a certain extent. But there are also some problems, such as:

(1) if the browser has new data to send before the service response, it can only create a new concurrent request, or try to break the current request first and create a new request.

(2) connection timeout is mentioned in both TCP and HTTP specifications, so the so-called long polling cannot last all the time. The connection between the server and the client needs to be connected and closed regularly, which increases the developer's workload. There are technologies that can extend the connection time, but this is not the mainstream solution.

3.Applet and Flash (coming off the shelves)

II. Brief introduction to WebSocket

WebSocket is a protocol for duplex communication over a single TCP connection, which has been set as a standard by W3C. Using WebSocket can make the data exchange between the client and the server easier. It allows the server to actively push data to the client. In the WebSocket protocol, the browser and the server only need to complete a handshake to establish a persistent connection and carry out two-way data transmission.

WebSocket uses the protocol upgrade feature of HTTP/1.1. A WebSocket request first uses an abnormal HTTP request to access a URL in a specific mode. The URL has two modes, ws and wss, corresponding to HTTP and HTTPS in the HTTP protocol. There is a Connection:Upgrade field in the request header indicating that the client wants to upgrade the protocol, and there is also a Upgrade:websocket field indicating that the client wants to upgrade the request protocol to WebSocket protocol. Together, these two fields tell the server to upgrade the connection to a duplex protocol such as WebSocket. If the server agrees to upgrade the protocol, then after the handshake is completed, text messages or other binary messages can be sent in both directions at the same time without shutting down and reconnecting. At this time, the relationship between the client and the server is peer-to-peer, and they can actively send messages to each other. Compared with traditional solutions, WebSocket has the following characteristics:

(1) when using WebSocket, you need to create a connection first, which makes WebSocket a stateful protocol, and some status information (such as identity authentication, etc.) can be omitted in the subsequent traffic process.

(2) WebSocket connects on port 80 (ws) or 443 (wss), which is the same as the port used by HTTP, so that almost all firewalls will not block WebSocket connections.

(3) WebSocket uses HTTP protocol for handshake, so it can be directly integrated into web browsers and HTTP servers without additional cost.

(4) heartbeat messages (ping and pong) will be pushed repeatedly to keep WebSocket in a consistent active state.

(5) using this protocol, both the server and the client can know when the message starts or arrives.

(6) A special closing message will be sent when the Websocket connection is closed.

(7) WebSocket supports cross-domain, which can avoid the restriction of Ajax.

(8) the HTTP specification requires browsers to limit concurrent connections to two connections per hostname, but when we use WebSocket, this restriction does not exist when the handshake is complete, because the connection is no longer a HTTP connection

(9) WebSocket protocol supports extension, and users can extend the protocol to implement some custom sub-protocols.

(10) better binary support and better compression effect

III. Spring Boot integrates WebSocket

1. Send messages in groups

Create the project: first create the Spring Boot project and add the following dependencies

Org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-websocket org.webjars webjars-locator-core 0.35 org.webjars sockjs-client 1. 1.2 org.webjars stomp-websocket 2.3.3-1 org.webjars jquery 3.3.1-1

Spring-boot-starter-websocket is dependent on WebSocket, and the rest are front-end libraries. Use jar packages to manage these front-end libraries, and use webjsr to add front-end libraries to the project. Static resources have been added to the Spring Boot project by default, so you can directly use the

two。 Configure WebSocket

The Spring framework provides WebSocket-based STOMP support. STOMP is a simple interoperable protocol that is usually used for asynchronous messaging between clients through intermediate servers. The WebSocket configuration is as follows:

@ Configuration@EnableWebSocketMessageBrokerpublic class WebSocketConfig implements WebSocketMessageBrokerConfigurer {@ Override public void configureMessageBroker (MessageBrokerRegistry registry) {registry.enableSimpleBroker ("/ topic"); registry.setApplicationDestinationPrefixes ("/ app");} @ Override public void registerStompEndpoints (StompEndpointRegistry registry) {registry.addEndpoint ("/ chat"). WithSockJS ();}}

Code interpretation:

(1) Custom WebSocketConfig is inherited from WebSocketMessageBrokerConfigurer for WebSocket configuration, and then the WebSocket message broker is enabled through @ EnableWebSocketMessageBroker annotation.

(2) registry.enableSimpleBroker ("/ topic") means to set the prefix of the message broker, that is, if the prefix of the message is "/ topic", the message will be forwarded to the broker, and the message broker will broadcast the message to the currently connected client.

(3) registry.setApplicationDestinationPrefixes ("/ app") means to configure one or more prefixes to filter out messages that need to be processed by the annotation method.

(4) registry.addEndpoint ("/ chat") .withSockJS () defines an edPoint with the prefix "/ chat" and enables sockjs support. Sockjs can solve the problem of browser compatibility with WebSocket, and the client will establish a WebSocket connection through the URL configured here.

3. Define Controller

Define Controller to implement message processing

@ RestControllerpublic class GreetingController {@ MessageMapping ("/ hello") @ SendTo ("/ topic/greetings") public Message greeting (Message message) throws Exception {return message;}}

According to the second configuration, the @ MessageMapping ("/ hello") annotation method will be used to receive the message sent by the "/ app/hello" path. After the message is processed in the annotation method, the message will be forwarded to the path defined by @ SendTo, while the path of @ SendTo is a path with "/ topic", so the message will be given to the message broker broker and broadcast by broker.

4. Foreground page

Single chat group chat, please enter user name: disconnected, please enter chat content: send group chat in progress. Please enter chat content: target user: send

5. Js logic for pages and websocket

Var stompClient = null;function setConnected (connected) {$("# connect"). Prop ("disabled", connected); $("# disconnect"). Prop ("disabled",! connected); if (connected) {$("# conversation"). Show (); $("# chat"). Show ();} else {$("# conversation"). Hide (); $("# chat"). Hide () } $("# greetings"). Html ("");} function connect () {if (! $("# name"). Val ()) {return;} var socket = new SockJS ('/ chat'); stompClient = Stomp.over (socket); stompClient.connect ({}, function (frame) {setConnected (true)) StompClient.subscribe ('/ topic/greetings', function (greeting) {showGreeting (JSON.parse (greeting.body));});} function disconnect () {if (stompClient! = = null) {stompClient.disconnect ();} setConnected (false) } function sendName () {stompClient.send ("/ app/hello", {}, JSON.stringify ({'name': $("# name"). Val (),' content': $("# content"). Val ()});} function showGreeting (message) {$("# greetings") .append ("" + message.name + ":" + message.content + "") } $(function () {("# connect") .click (function () {connect ();}); $("# disconnect") .click (function () {disconnect ();}); $("# send") .click (function () {sendName ();});})

Code interpretation:

(1) the connect method means to establish a WebSocket connection. When establishing a WebSocket connection, the user must enter a user name before establishing a connection.

(2) meaning in the method body: use SockJS to establish a connection, and then create a STOMP instance to initiate the request. In the successful connection callback method, first call setConnected (true); method for page setup, then call the subscribe method in STOPM to subscribe to the message sent by the server, and display the message sent by the server (using the showGreeting method)

(3) call the disconnect method in STOMP to disconnect a WebScoket connection.

5. Entity class

Public class Message {private String name; private String content;.getter,setter.}

6. Transform message to send Controller

The @ SendTo annotation is used to send messages. Messages processed by the method are forwarded to broker and broadcast by broker. In addition to @ SendTo annotation, Spring also provides SimpMessagingTemplate classes to give developers more flexibility to send messages. You can modify the above Controller using SimpMessagingTemlate. The modification results are as follows:

RestControllerpublic class GreetingController {@ Autowired SimpMessagingTemplate simpMessagingTemplate; @ MessageMapping ("/ hello") public void greeting (Message message) throws Exception {simpMessagingTemplate.convertAndSend ("/ topic/greetings", message);}}

Four. message point-to-point transmission

1. Add dependency

Since it is peer-to-peer, it should have the concept of the user, so first add the dependency of Spring Security to the project, as follows:

Org.springframework.boot spring-boot-starter-security

two。 Configure Spring Security

Configure spring security to add two users, and configure all addresses to be authenticated before access. The code is as follows:

@ Configurationpublic class WebSecurityConfig extends WebSecurityConfigurerAdapter {@ Bean PasswordEncoder passwordEncoder () {return new BCryptPasswordEncoder () Password encrypted: 123 * / @ Override protected void configure (AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication () .withUser ("Qi * *") .password ("$2a$10 $RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq") .password ("admin") .and () .withUser ("Xin *") .password ("$2a$10 $RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq") Password ("user") .and () .withUser ("Li * *") .password ("$2a$10 $RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq") .password ("user") .and () .withUser ("Yue * *") .password ("$2a$10 $RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq") .password ("user") .and () .withUser ("still * *") ) .password ("$2a$10 $RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq") .password ("user") } @ Override protected void configure (HttpSecurity http) throws Exception {http.authorizeRequests () .anyRequest () .authenticated () and () .formLogin () .permitAll ();}}

3. The configuration code of the modified WebSocket is as follows:

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

Code interpretation:

Registry.enableSimpleBroker ("/ topic") has been modified and a prefix "/ queue" has been added to facilitate the management of group and peer-to-peer messages.

4. Configure Controller

Modify the Controller of WebSocket as follows:

@ RestControllerpublic class GreetingController {@ Autowired SimpMessagingTemplate simpMessagingTemplate; / * Group messages * @ param message * @ return * @ throws Exception * / @ MessageMapping ("/ hello") @ SendTo ("/ topic/greetings") public Message greeting (Message message) throws Exception {return message * @ param principal * @ param chat * @ throws Exception * / @ MessageMapping ("/ chat") public void chat (Principal principal, Chat chat) throws Exception {String from=principal.getName (); chat.setFrom (from); simpMessagingTemplate.convertAndSendToUser (chat.getTo (), "/ queue/chat", chat);;}}

Code interpretation:

(1) Group messaging is still implemented using @ SendTo, while peer-to-peer messaging is implemented with SimpMessagingTemplate.

(2) @ MessageMapping ("/ chat") indicates that the message from the "/ app/chat" path will be processed by the chat method. The first parameter of the chat method, Principal, can be used to obtain the information of the currently logged in user, and the second parameter is the message sent by the client.

(3) in the chat method, you first get the user name of the currently logged-in user, set it to the from property of the chat object, and then send the message to the to attribute of chat.

(4) the method used to send messages is convertAndSendToUser, in which the convertAndSend method is called internally, and the message path is processed.

5. Message entity class:

Public class Chat {private String to; private String from; private String content; .getter, setter omitted.}

Code interpretation:

Chat is a common javaBean,to attribute that indicates the target user of the message, form indicates where the message comes from, and content is the main content of the message.

6. Foreground page-online chat page (created in onlinechat.html)

Single chat Please enter chat content: target user: send

5. Js logic for pages and websocket

Var stompClient = null;function setConnected (connected) {$("# connect"). Prop ("disabled", connected); $("# disconnect"). Prop ("disabled",! connected); if (connected) {$("# conversation"). Show (); $("# chat"). Show ();} else {$("# conversation"). Hide (); $("# chat"). Hide () } $("# greetings"). Html ("");} function connect () {if (! $("# name"). Val ()) {return;} var socket = new SockJS ('/ chat'); stompClient = Stomp.over (socket); stompClient.connect ({}, function (frame) {setConnected (true)) StompClient.subscribe ('/ topic/greetings', function (greeting) {showGreeting (JSON.parse (greeting.body));});} function disconnect () {if (stompClient! = = null) {stompClient.disconnect ();} setConnected (false) } function sendName () {stompClient.send ("/ app/hello", {}, JSON.stringify ({'name': $("# name"). Val (),' content': $("# content"). Val ()});} function showGreeting (message) {$("# greetings") .append ("" + message.name + ":" + message.content + "") } $(function () {("# connect") .click (function () {connect ();}); $("# disconnect") .click (function () {disconnect ();}); $("# send") .click (function () {sendName ();});})

Code interpretation:

(1) after a successful connection, the subscription address is "/ user/queue/chat", which has more "/ user" prefix than the address configured by the server. This is because the path prefix is automatically added to the SimpMessagingTemplate class.

(2) the path for sending chat messages is "/ app/chat"

(3) there is a to field in the content of the message sent, which is used to describe the target user of the message.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report