81,092
社区成员
发帖
与我相关
我的任务
分享
@OnOpen
public void onOpen(Session session, EndpointConfig config)
{
SessionSet.add(session);
//打算通过session实现,但是没缕清思路
httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
String token = session.getPathParameters().get("token");// token是前端打开websocket连接时带的参数信息,如果没有表示是打开的APP没有登陆过
// 客户没有在APP端操作退出操作,直接kill程序之后再次打开程序的场景
// 或者客户将程序挂在后台,系统将APP kill之后,用户再次打开,需要重新连接websocket
// 以上情况下,客户端是带有token信息的 token要不要带Bearer 还需要跟前端确认
if (!Stringutils.isEmptyString(token))
{
String userId = manager.getUserByToken(token);
String redisToken = redisUtils.get(userId);
if (ValidateHelper.isEmptyString(redisToken))
{
// 如果Redis里面的token是空的,说明登录已经失效了
sendObject(session, new Response<>(LOGIN_DISABLED, LOGIN_DISABLED.getErrMsg());
}
if (!Stringutils.isEmptyString(redisToken) && !redisToken.equals(token))
{
// 如果Redis里面存在该用户的token,并且该token跟传入的token不一致,那么就说明该用户在其他地方登陆过,踢出现有用户
sendObject(session, new Response<>(LOGIN_REPEAT.getErrCode(), LOGIN_REPEAT.getErrMsg()));
}
// 如果密码没有失效,并且没有被替换,说明当前登陆的用户的唯一登陆的了
uidSessionMap.put(userId, session);
}
}
@OnMessage
public void onMessage(String message, Session session)
{
log.info("来自客户端的消息:{}", message);
if (Boolean.parseBoolean(message)) // 此处是用来测试的代码
{
httpSession.setAttribute(session.getId(), message);
loginOfflinePublisher.send(session.getId() + ":" + message);
sendMessage(session, message);
}
// 如果客户端传入的是token信息
if (message.startsWith("Bearer "))
{
// 获取到当前的token是属于哪个用户的
String userId = manager.getUserByToken(message.substring(7));
Session session1 = uidSessionMap.put(userId, session);
// 如果当前服务器没有登录用户的信息,就发布消息让其他服务器去检查自己是否有该用户的信息,有就踢出该用户
// 注意要把当前连接的session的信息传递过去,防止当前服务器把当前登录用户也给踢出去了(此处有问题)
if (Objects.isNull(session1))
{
loginOfflinePublisher.send(session.getId() + ":" + userId);
} else
{
// 如果在本服务器,直接踢出该用户
sendObject(session1, new Response<>(String.valueOf(LOGIN_REPEAT.getErrCode()), LOGIN_REPEAT.getErrMsg()));
}
}
}
@Slf4j
public class LoginOfflineListener implements MessageListener
{
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired // 一直无法注入,提示No thread-bound request found
private HttpSession httpSession;
@Override
public void onMessage(Message message, byte[] pattern)
{
doBusiness(message);
}
/**
* 打印 message body 内容
*
* @param message
*/
public void doBusiness(Message message)
{
log.info("收到Redis发布的消息...");
String value = (String) stringRedisTemplate.getValueSerializer().deserialize(message.getBody());
// 收到发布的消息后,Redis向其它服务器发布订阅的消息
String[] sessionIdAndUserId = new String[0];
if (value != null)
{
sessionIdAndUserId = value.split(":");
}
String attribute = (String) WebSocketServer.httpSession.getAttribute(sessionIdAndUserId[0]);
// 在这里排除当前机器
if (!ValidateHelper.isEmptyString(attribute) && sessionIdAndUserId.length > 1 && !attribute.equals(sessionIdAndUserId[1]))
{
WebSocketServer.sendMessage(sessionIdAndUserId);
}
}
}