spring - 如何使用spring stomp websocket拒绝用户订阅或取消订阅服务器端的用户
问题描述
我试图在用户被管理员禁止时强制取消订阅,并在用户被禁止时阻止该用户订阅。禁令状态保存在我的数据库中。我目前有一个拦截器来执行阻塞,preSend
但是当我抛出异常时连接关闭。无论如何在不关闭套接字连接的情况下拒绝订阅消息吗?
@Override
public Message<?> preSend(@NonNull Message<?> message, @NonNull MessageChannel channel) {
StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(message);
if (StompCommand.SUBSCRIBE.equals(headerAccessor.getCommand())) {
checkIsBanned(headerAccessor.getDestination(), headerAccessor.getUser());
}
return message;
}
private void checkIsBanned(String destination, Principal principal) {
if (destination == null || !destination.matches(CHAT_TOPIC_REGEX)) {
return;
}
String errorMessage = resourceBundle.getMessage("err.channel.banned");
if (!(principal instanceof OAuth2Authentication) || !(((OAuth2Authentication) principal).getPrincipal() instanceof SUserDetails)) {
throw new MessagingException(errorMessage);
}
String channelId = destination.split("/")[3];
Long profileId = getProfileId(principal);
if (profileId == null) {
throw new MessagingException(errorMessage);
}
channelUserRepo.findByChannelIdAndUserId(channelId, profileId).filter(ChannelUser::isBanned).orElseThrow(() -> new MessagingException(errorMessage));
}
private Long getProfileId(Principal principal) {
return ((SUserDetails) ((OAuth2Authentication) principal).getPrincipal()).getProfileId();
}
当管理员禁止用户时,我还尝试通过让用户退出userRegistry
并删除他的订阅来强制取消订阅,但这没有用。有没有办法做到这一点?
解决方案
我想我设法通过仅返回 null 来拒绝订阅,preSend
它将忽略订阅消息而不是抛出错误。您还可以通过套接字向用户发送通知来通知用户。
public ChatInterceptor(ResourceBundle resourceBundle, ChannelUserRepository channelUserRepo, @Lazy SimpMessagingTemplate socket) {
this.resourceBundle = resourceBundle;
this.channelUserRepo = channelUserRepo;
this.socket = socket;
}
@Override
public Message<?> preSend(@NonNull Message<?> message, @NonNull MessageChannel channel) {
StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(message);
if (StompCommand.SUBSCRIBE.equals(headerAccessor.getCommand())) {
if (checkIsBanned(headerAccessor.getDestination(), headerAccessor.getUser())) {
socket.convertAndSendToUser(getSocketUsername(headerAccessor.getUser()), ServicePath.NOTIFICATION,
new SocketResponse(resourceBundle.getMessage("err.channel.banned"), ERROR));
return null;
}
}
return message;
}
推荐阅读
- mongodb - Mongoose 移除重复的社保客户
- ansible - 使用 ansible 解析 VMware DVSwitch json 的问题
- python-3.x - 熊猫将重复的第 2 列变成标题
- google-apps-script - 我正在尝试使用 Google Appscript Google Classroom 列出课程作业材料
- javascript - TS:从链式方法模式获取接口
- angular - 单元测试在 rxjs skipwhile 停止
- java - 如何在 Android 中实现 CountDownTimer 减少时间功能
- python - AttributeError: 'Event' 对象没有属性 'path' plis ayuda
- r - R中的=stdev等价物是什么?
- c++ - 如何解决 GoLang 后端项目中的“无法删除 *.log”错误?