websocket增加鉴权整合springboot
【代码】websocket增加鉴权java后端实现以及vue前端调用。
·
后端代码实现
1.WebSocket类
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Description: 此注解相当于设置访问URL
*/
@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}")
public class WebSocket{
/**
* 线程安全Map
*/
private static ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<>();
//==========【websocket接受、推送消息等方法 —— 具体服务节点推送ws消息】========================================================================================
@OnOpen
public void onOpen(Session session, @PathParam(value = "userId") String userId) {
try {
sessionPool.put(userId, session);
} catch (Exception e) {
log.error(e.getMessage());
}
}
@OnClose
public void onClose(Session session, @PathParam("userId") String userId) {
try {
sessionPool.remove(userId);
log.info("【系统 WebSocket】连接断开,总数为:" + sessionPool.size());
} catch (Exception e) {
log.error(e.getMessage());
}
}
/**
* ws推送消息
*
* @param userId
* @param message
*/
public void pushMessage(String userId, String message) {
for (Map.Entry<String, Session> item : sessionPool.entrySet()) {
//userId key值= {用户id + "_"+ 登录token的md5串}
//TODO vue2未改key新规则,暂时不影响逻辑
if (item.getKey().contains(userId)) {
Session session = item.getValue();
try {
//update-begin-author:taoyan date:20211012 for: websocket报错 https://gitee.com/jeecg/jeecg-boot/issues/I4C0MU
synchronized (session) {
log.info("【系统 WebSocket】推送单人消息:" + message);
session.getBasicRemote().sendText(message);
}
//update-end-author:taoyan date:20211012 for: websocket报错 https://gitee.com/jeecg/jeecg-boot/issues/I4C0MU
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
}
/**
* ws遍历群发消息
*/
public void pushMessage(String message) {
try {
for (Map.Entry<String, Session> item : sessionPool.entrySet()) {
try {
item.getValue().getAsyncRemote().sendText(message);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
log.info("【系统 WebSocket】群发消息:" + message);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
/**
* ws接受客户端消息
*/
@OnMessage
public void onMessage(String message, @PathParam(value = "userId") String userId) {
if (!"ping".equals(message) && !WebsocketConst.CMD_CHECK.equals(message)) {
log.info("【系统 WebSocket】收到客户端消息:" + message);
} else {
log.debug("【系统 WebSocket】收到客户端消息:" + message);
}
try {
Session session = sessionPool.get(userId);
if(session!=null){
session.getBasicRemote().sendText(message);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
//------------------------------------------------------------------------------
}
/**
* 配置错误信息处理
*
* @param session
* @param t
*/
@OnError
public void onError(Session session, Throwable t) {
log.warn("【系统 WebSocket】消息出现错误");
log.warn(t.getMessage());
}
//==========【系统 WebSocket接受、推送消息等方法 —— 具体服务节点推送ws消息】========================================================================================
}
2.WebsocketFilter类
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* websocket 前端将token放到子协议里传入 与后端建立连接时需要用到http协议,此处用于校验token的有效性
**/
@Slf4j
public class WebsocketFilter implements Filter {
private static final String TOKEN_KEY = "Sec-WebSocket-Protocol";
@Autowired
private VerifyUtil verifyUtil;
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
String token = request.getHeader(TOKEN_KEY);
log.debug("Websocket连接 Token安全校验,Path = {},token:{}", request.getRequestURI(), token);
try {
verifyUtil.verifyToeken(token);
} catch (Exception exception) {
log.debug("Websocket连接 Token安全校验失败,IP:{}, Token:{}, Path = {},异常:{}", oConvertUtils.getIpAddrByRequest(request), token, request.getRequestURI(), exception.getMessage());
return;
}
HttpServletResponse response = (HttpServletResponse)servletResponse;
response.setHeader(TOKEN_KEY, token);
filterChain.doFilter(servletRequest, servletResponse);
}
}
3.WebSocketConfig 类
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
/**
* 注入ServerEndpointExporter,
* 这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
@Bean
public WebsocketFilter websocketFilter(){
return new WebsocketFilter();
}
@Bean
public FilterRegistrationBean getFilterRegistrationBean(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(websocketFilter());
//TODO 临时注释掉,测试下线上socket总断的问题
bean.addUrlPatterns("/websocket/*");
return bean;
}
}
前端调用
//初始化websocket的时候传入token即可
this.websock = new WebSocket(url,token);
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)