在SpringBoot项目中,用java实现websocket服务端,客户端发送Sec-WebSocket-Key后,服务端返回Sec-WebSocket-Accept
时间: 2023-11-22 08:57:01 浏览: 305
在SpringBoot项目中,可以使用Spring WebSocket模块来实现websocket服务端。在接收到客户端发送的Sec-WebSocket-Key后,服务端需要经过一系列的处理才能返回Sec-WebSocket-Accept。
以下是一个示例代码:
```java
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
import javax.websocket.server.ServerEndpointConfig;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Map;
@Component
public class WebSocketConfig extends AbstractWebSocketHandler {
// 服务端接收到客户端发送的Sec-WebSocket-Key后,需要经过一系列的处理才能返回Sec-WebSocket-Accept
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
String key = session.getAttributes().get("key").toString();
String secWebSocketAccept = generateSecWebSocketAccept(key);
session.sendMessage(new TextMessage(secWebSocketAccept));
}
// 生成Sec-WebSocket-Accept的方法
private String generateSecWebSocketAccept(String key) {
String guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
String keyConcat = key + guid;
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(keyConcat.getBytes());
byte[] byteDigest = md.digest();
byte[] accept = Base64.getEncoder().encode(byteDigest);
return new String(accept, "UTF-8");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
}
// 配置WebSocket
@Configuration
@EnableWebSocket
public class WebSocketConfig extends WebSocketConfigurer {
@Autowired
private WebSocketConfig webSocketHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(webSocketHandler, "/ws").addInterceptors(new HandshakeInterceptor() {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
String key = request.getHeaders().get("Sec-WebSocket-Key").get(0);
attributes.put("key", key);
return true;
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
}
}).setHandshakeHandler(new DefaultHandshakeHandler() {
@Override
protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) {
return new WebSocketPrincipal();
}
});
}
}
```
在上述代码中,`WebSocketConfig`类继承自`AbstractWebSocketHandler`,并且实现了`afterConnectionEstablished`方法,该方法会在websocket连接建立后自动被调用。在该方法中,可以获取到客户端发送的Sec-WebSocket-Key,并且调用`generateSecWebSocketAccept`方法生成Sec-WebSocket-Accept并返回给客户端。
`generateSecWebSocketAccept`方法的实现中,需要将Sec-WebSocket-Key与一个GUID进行拼接,然后使用SHA-1算法进行加密,并使用Base64编码后返回,具体的实现可以参考上述代码。
在`WebSocketConfig`类中,还需要注册WebSocket处理器,并且添加一个握手拦截器,在握手拦截器中可以获取到客户端发送的Sec-WebSocket-Key,并将其保存到attributes中,以便在`afterConnectionEstablished`方法中使用。同时,在握手拦截器中需要返回true,表示握手成功。
至此,客户端发送Sec-WebSocket-Key后,服务端可以返回Sec-WebSocket-Accept了。
阅读全文