对于每个 Spring websocket 事件,Principal 为 null

2023-11-30

我试图从 Spring websocket SessionConnectEvent 获取主体用户名,但它在每个侦听器上均为空。我可能做错了什么?

为了实现它,我遵循了您可以在这里找到的答案:如何使用 Spring 4 捕获 webSocket 服务器中的连接事件?

@Slf4j
@Service
public class SessionEventListener {

    @EventListener
    private void handleSessionConnect(SessionConnectEvent event) {
        SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.wrap(event.getMessage());
        String sessionId = headers.getSessionId();
        log.debug("sessionId is " + sessionId);
        String username = headers.getUser().getName(); // headers.getUser() is null
        log.debug("username is " + username);
    }

    @EventListener
    private void handleSessionConnected(SessionConnectEvent event) {
        SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.wrap(event.getMessage());
        String sessionId = headers.getSessionId();
        log.debug("sessionId is " + sessionId);
        String username = headers.getUser().getName(); // headers.getUser() is null
        log.debug("username is " + username);
    }

    @EventListener
    private void handleSubscribeEvent(SessionSubscribeEvent event) {
        SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.wrap(event.getMessage());
        String sessionId = headers.getSessionId();
        log.debug("sessionId is " + sessionId);
        String subscriptionId = headers.getSubscriptionId();
        log.debug("subscriptionId is " + subscriptionId);
        String username = headers.getUser().getName(); // headers.getUser() is null
        log.debug("username is " + username);
    }

    @EventListener
    private void handleUnsubscribeEvent(SessionUnsubscribeEvent event) {
        SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.wrap(event.getMessage());
        String sessionId = headers.getSessionId();
        log.debug("sessionId is " + sessionId);
        String subscriptionId = headers.getSubscriptionId();
        log.debug("subscriptionId is " + subscriptionId);
        String username = headers.getUser().getName(); // headers.getUser() is null
        log.debug("username is " + username);
    }

    @EventListener
    private void handleSessionDisconnect(SessionDisconnectEvent event) {
        SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.wrap(event.getMessage());
        log.debug("sessionId is " + event.getSessionId());
        String username = headers.getUser().getName(); // headers.getUser() is null
        log.debug("username is " + username);
    }

}

这是我的安全配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .anyRequest()
            .permitAll()
            .and().csrf().disable();
    }
}

由于我没有实现身份验证机制,Spring 没有足够的信息来提供主体用户名。所以我要做的就是配置一个生成主体的 HandshakeHandler。

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    public static final String ENDPOINT_CONNECT = "/connect";
    public static final String SUBSCRIBE_USER_PREFIX = "/private";
    public static final String SUBSCRIBE_USER_REPLY = "/reply";
    public static final String SUBSCRIBE_QUEUE = "/queue";

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker(SUBSCRIBE_QUEUE, SUBSCRIBE_USER_REPLY);
        registry.setUserDestinationPrefix(SUBSCRIBE_USER_PREFIX);
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint(ENDPOINT_CONNECT)
                // assign a random username as principal for each websocket client
                // this is needed to be able to communicate with a specific client
                .setHandshakeHandler(new AssignPrincipalHandshakeHandler())
                .setAllowedOrigins("*");
    }

}
/**
 * Assign a random username as principal for each websocket client. This is
 * needed to be able to communicate with a specific client.
 */
public class AssignPrincipalHandshakeHandler extends DefaultHandshakeHandler {
    private static final String ATTR_PRINCIPAL = "__principal__";

    @Override
    protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) {
        final String name;
        if (!attributes.containsKey(ATTR_PRINCIPAL)) {
            name = generateRandomUsername();
            attributes.put(ATTR_PRINCIPAL, name);
        } else {
            name = (String) attributes.get(ATTR_PRINCIPAL);
        }
        return new Principal() {
            @Override
            public String getName() {
                return name;
            }
        };
    }

    private String generateRandomUsername() {
        RandomStringGenerator randomStringGenerator = 
                new RandomStringGenerator.Builder()
                    .withinRange('0', 'z')
                    .filteredBy(CharacterPredicates.LETTERS, CharacterPredicates.DIGITS).build();
        return randomStringGenerator.generate(32);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对于每个 Spring websocket 事件,Principal 为 null 的相关文章

随机推荐

  • 如何对 NetworkX 中创建的图 g 进行聚类?

    我正在尝试将聚类应用于数据集 在此之前 我必须将图划分为 n 个簇 但我不知道该怎么做 Suppose 边缘列表你的未加权的 and 不定向的 graph保存在文件edges txt中 您可以按照以下步骤对图的节点进行聚类 Step 1 g
  • 在调用委托之前将我的空检查代码变灰

    我在 VS 2015 中编写统一代码 这意味着它是在 c 4 中并且 null 条件运算符不可用 在调用委托之前 我进行了空检查 但代码是灰色的 是不是说灰码和注释一样无效呢 如果是这样 我应该怎么做才能防止调用空委托 public del
  • 无法从 grails 项目构建 war

    我正在构建 Grails 2 4 4 项目 我遇到了非常奇怪的问题 我可以 运行应用程序 我可以 编译 它 但我不能 战争 或 运行战争 它 将 src groovy 目录中的 Enum 类 AlertType 导入到域类 Alert 时出
  • VSTO - MS Office“配色方案”更改事件

    使用 VSTO 如何获取 MS Office 配色方案更改的通知 希望 Office 2010 中存在更好的东西 以下是我在 Office 2007 和 Word 中使用的内容 这不是任何通知 只是要检查的内容 const string O
  • AccountManager:invalidateAuthToken 不会使令牌失效

    我正在尝试从存储在 Android 设备中的 Google 帐户获取全新的令牌 但我得到的只是我过去几天缓存的旧令牌 看起来它被缓存在手机的某个地方 甚至没有发送互联网请求 我在没有互联网连接的情况下在应用程序中进行了测试 并且返回了相同的
  • PL/SQL 过程的同步。如何保证程序一次只执行一个? [复制]

    这个问题在这里已经有答案了 某些 PL SQL 过程需要花费大量时间进行评估 如重新计算和更新大量数据 我想限制将此过程评估为单个的执行上下文的数量 如果其他上下文执行它 则什么也不做 但我不知道在 PL SQL 代码中使用哪些原子操作 N
  • 接口 VS API VS 公共类

    我对这三个术语的含义和区别有点困惑 接口 APIs 公开课 我之前问过 API 和 Public 类之间有什么区别吗 这是问题 公共方法与公共 API 我明白了 但现在有了新概念界面 我又对Interface和API以及Public cla
  • 为什么 numpy 列表访问比普通 python 慢?

    我的印象是 numpy 对于列表操作会更快 但以下示例似乎表明情况并非如此 import numpy as np import time def ver1 a i for i in range 40 b 0 for i in range 4
  • Visual Studio 2015 jQuery 智能感知不工作

    因此 我创建了一个 Visual Studio 2015 空 ASP net Core 应用程序 并尝试使用 Bower 添加 jQuery 但它没有获取 jQuery 的智能感知 它显示一条警告 指出 智能感知无法确定准确的值 完成列表
  • Bash 脚本数组转 csv

    我想从我的数组中执行逗号分隔的字符串 在我的脚本中我收集数据到数组outputArr然后我想echo来检查一下 但现在我被困住了 我想使用以下命令在控制台上打印它 echo outputArr 但我得到了错误的输出 所以我尝试调试它并这样写
  • 如何判断数据库更新是否成功?

    我正在尝试修改一些遗留的ASP经典代码 并且我对ASP了解不多 如何判断数据库插入 更新或删除是否失败 我所说的 失败 是指它要么引发错误 要么影响零行 以下是 ASP 文件中已有的用于设置数据库连接的代码 On Error Resume
  • 外包RSA加密和解密的问题

    我在 RSA 加密和解密方面遇到问题 我正在 android 中开发 想外包 RSA 加密和解密 在我尝试外包之前 我的源代码运行良好 我创建了私钥和公钥 并将其保存为 private key 和 public key 该错误是由该方法引起
  • 如何在 JavaScript 变量中存储多个 jQuery 选择器?

    显然 如果多次使用 jQuery 选择器 将它们存储在变量中是个好主意 not如果只使用一次是个好主意 我的问题是 如何在变量中存储可互换使用的多个选择器 例如 假设我选择 object1 object2 然后我选择 object1 我将如
  • 如何以编程方式更新元素并将其添加到 XSD

    我需要以编程方式更新 java 中的现有 XSD 如下所示
  • group_concat 结果在 IN 条件下不起作用

    有没有可能的方法将 group concat 的结果放入 SQL 查询的 IN 条件中 在网络主表中 我在 IndustryId 列中有逗号分隔的字段 喜欢 userId industryId 123 3831 123 2832 3832
  • 错误:类型 List 的方法 getId() 未定义

    我有一个方法来创建类对象列表 public List
  • Tkinter 将视频插入窗口[重复]

    这个问题在这里已经有答案了 我目前有这段代码用于从 tkinter 程序打开 mp4 文件 import os from tkinter import app Tk app title Video Player Fcanvas Canvas
  • 如何更改菜单栏中子菜单的标签颜色?

    我想使用菜单栏更改子菜单的标签颜色 我正在使用的代码如下
  • 转义 Java RegEx 元字符

    我正在尝试转义 Java 中的 RegExp 元字符 以下是我想要的 INPUT STRING This is test OUTPUT STRING This is test 这就是我目前正在做的事情 但它不起作用 String input
  • 对于每个 Spring websocket 事件,Principal 为 null

    我试图从 Spring websocket SessionConnectEvent 获取主体用户名 但它在每个侦听器上均为空 我可能做错了什么 为了实现它 我遵循了您可以在这里找到的答案 如何使用 Spring 4 捕获 webSocket