WebSocket实现鉴权⽅案
⽬录
WebSocket是⼀种在单个TCP连接上进⾏全双⼯通信的协议。它使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。浏览器只需要和服务端完成⼀次握⼿,两端就可以建⽴持久性链接来进⾏双向通信。但在实际的应⽤中为了防⽌恶意的未经授权的客户端发起链接,此时就需要客户端在与服务端建⽴链接时携带指定的授权信息,服务端在响应握⼿时对携带的授权协议信息进⾏鉴权,校验成功后⽅可放⾏从⽽握⼿成功建⽴长链接。那么对于websocket⽆法携带header 信息和cookie我们该如何向服务端传输授权信息进⽽鉴权呢(如:⾃定义token,jwt,⽤户账号信息等),看下⽂分解。
⼀、springboot+websocket搭建
1.1.使⽤依赖
// gradle
implementation 'org.springframework.boot:spring-boot-starter-websocket'
// maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
1.2.WebSocketInterceptor鉴权
鉴权逻辑将在这⾥做,待下⽂分解
import Map;
import Logger;
import LoggerFactory;
import ServerHttpRequest;
import ServerHttpResponse;
import Component;
import WebSocketHandler;
import HandshakeInterceptor;
@Component
public class WebSocketInterceptor implements HandshakeInterceptor {
/**
* ⽇志
*/
private static final Logger log = Logger(WebSocketInterceptor.class);
/**
* 握⼿之前
*
* @param request request
* @param response response
* @param wsHandler handler
* @param attributes 属性
* @return 是否握⼿成功:true-成功,false-失败
*/
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes){
//这⾥做客户端鉴权业务处理,下⽂分解
return true;
}
/**
* 握⼿后
*
* @param request request
* @param response response
* @param wsHandler wsHandler
* @param exception exception
*/
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception exception){
log.info("handshake success!");
}
}
1.3.MyWebSocketHandler处理器
import IOException;
import Map;
import ConcurrentHashMap;
import AtomicInteger;
import Logger;
import LoggerFactory;
import CloseStatus;
import TextMessage;
import WebSocketSession;
import TextWebSocketHandler;
public class MyWebSocketHandler extends TextWebSocketHandler {
/**
* ⽇志
*/
private static final Logger log = Logger(MyWebSocketHandler.class);
/**
* 静态变量,⽤来记录当前在线连接数
* 静态变量,⽤来记录当前在线连接数
*/
private static AtomicInteger onlineNum =new AtomicInteger();
/**
* 存放每个客户端连接对象
*/
private static ConcurrentHashMap<Integer, WebSocketSession> sessionPools =new ConcurrentHashMap<>(); /**
* 在线⼈数加⼀
*/
public static void addOnlineCount(){ onlineNum.incrementAndGet();}
/**
* 在线⼈数减⼀
前端websocket怎么用*/
public static void subOnlineCount(){
onlineNum.decrementAndGet();
}
/**
* 接受客户端消息
*
* @param session session
* @param message message
* @throws IOException e
*/
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message)throws IOException {
session.sendMessage(new TextMessage(String.format("收到⽤户:【%s】发来的【%s】",
}
/**
* 建⽴连接后发送消息给客户端
*
* @param session session
* @throws Exception e
*/
@Override
public void afterConnectionEstablished(WebSocketSession session)throws Exception {
String uid = Attributes().get("uid").toString();
WebSocketSession put = sessionPools.put(Integer.parseInt(uid), session);
if(put ==null){
addOnlineCount();
}
session.sendMessage(new TextMessage("connection to ws succeeded! online number:"+ onlineNum)); }
/**
* 连接关闭后
*
* @param session session
* @param status status
* @throws Exception e
*/
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status)throws Exception {
String uid = Attributes().get("uid").toString();
subOnlineCount();
log.info("disconnect!");
}
/**
* 发送⼴播消息
*
* @param message 消息内容
* @param message 消息内容
*/
public static void sendTopic(String message){
if(sessionPools.isEmpty()){
return;
}
for(Map.Entry<Integer, WebSocketSession> entry : Set()){ try{
}catch(IOException e){
e.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}
}
}
/
**
* 点对点发送消息
*
* @param uid ⽤户
* @param message 消息
*/
public static void sendToUser(String uid, String message){
WebSocketSession socketSession = (Integer.parseInt(uid));
if(socketSession ==null){
return;
}
try{
socketSession.sendMessage(new TextMessage(message));
}catch(IOException e){
<("send to user:{}, error! data:{}", uid, message);
}
}
}
1.4.WebSocketConfig配置
import Bean;
import Configuration;
import WebSocketHandler;
import EnableWebSocket;
import WebSocketConfigurer;
import WebSocketHandlerRegistry;
import Resource;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
/**
* 注⼊
*/
@Resource
private WebSocketInterceptor webSocketInterceptor;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry){
webSocketHandlerRegistry
//添加myHandler消息处理对象,和websocket访问地址
.addHandler(myHandler(),"/ws")
//设置允许跨域访问
.setAllowedOrigins("*")
//添加可实现⽤户链接前进⾏权限校验等操作
.addInterceptors(webSocketInterceptor);
}
@Bean
public WebSocketHandler myHandler(){
return new MyWebSocketHandler();
}
}
1.5.前端连接
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论