You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keycloak保护的WebSocket连接令牌刷新及ActiveMQ Artemis验证策略问题

ActiveMQ Artemis STOMP WebSocket 令牌验证问题解决方案

一、仅在连接阶段验证令牌

要实现连接成功后不再校验令牌,可通过以下两种方式配置:

1. 自定义STOMP认证器

实现org.apache.activemq.artemis.core.protocol.stomp.StompAuthenticator接口,仅在authenticate方法中执行令牌验证逻辑,后续操作(订阅、取消订阅等)直接放行。

示例代码片段:

public class OneTimeStompAuthenticator implements StompAuthenticator {
    private final KeycloakSecurityContextFactory contextFactory;

    @Override
    public AuthenticationResult authenticate(Channel channel, StompFrame connectFrame) {
        // 从CONNECT帧提取令牌并通过Keycloak验证
        String token = connectFrame.getHeader("token");
        // 执行Keycloak令牌验证逻辑,返回认证结果
        return AuthenticationResult.success(...);
    }

    @Override
    public boolean authorize(Channel channel, StompFrame frame) {
        // 连接成功后所有操作直接授权通过
        return true;
    }
}

在broker.xml的STOMP连接器中配置该认证器:

<acceptor name="stomp-ws-acceptor">
    <factory-class>org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
    <param name="protocols" value="STOMP"/>
    <param name="port" value="61614"/>
    <param name="stompAuthenticatorClass" value="com.yourpackage.OneTimeStompAuthenticator"/>
</acceptor>

2. 调整Keycloak安全域配置

修改keycloak.json,配置策略强制器仅对CONNECT帧对应的路径进行验证,忽略后续STOMP操作:

{
  "policy-enforcer": {
    "paths": [
      {
        "path": "/stomp/connect",
        "enforcement-mode": "ENFORCING"
      },
      {
        "path": "/stomp/*",
        "enforcement-mode": "DISABLED"
      }
    ]
  }
}

同时在broker.xml的安全域中确保仅连接时触发Keycloak验证:

<security-domain name="keycloak" type="Keycloak">
    <param name="keycloak-config-file" value="keycloak.json"/>
    <param name="validate-on-demand" value="false"/>
</security-domain>

二、更新续期后的令牌

若无法实现仅连接时验证,可通过以下方式告知Artemis更新客户端令牌:

1. 自定义帧触发令牌更新

客户端令牌续期后,发送一个自定义SEND帧(携带新令牌),服务器通过拦截器捕获并更新会话凭证:

  • 客户端发送的帧示例:
SEND
destination:/control/update-token
token:<new-jwt-token>

^@
  • 服务器端配置拦截器,实现org.apache.activemq.artemis.core.protocol.stomp.StompInterceptor:
public class TokenUpdateInterceptor implements StompInterceptor {
    @Override
    public boolean intercept(StompFrame frame, RemotingConnection connection) {
        if ("/control/update-token".equals(frame.getHeader("destination"))) {
            String newToken = frame.getHeader("token");
            // 验证新令牌有效性(可选)
            // 更新当前连接的安全上下文
            KeycloakSecurityContext newContext = ...; // 从新令牌构建上下文
            connection.putAttachment("keycloak.security.context", newContext);
            // 消费该帧,不转发到队列
            return false;
        }
        return true;
    }
}

在broker.xml中注册拦截器:

<stomp-connector>
    <interceptors>
        <class-name>com.yourpackage.TokenUpdateInterceptor</class-name>
    </interceptors>
</stomp-connector>

2. 利用Artemis会话API更新

通过拦截器获取当前会话的安全凭证,替换为新令牌对应的上下文。确保Keycloak客户端能解析新令牌并生成有效的安全上下文,覆盖原有会话的凭证信息。

内容的提问来源于stack exchange,提问作者Alberto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 16:55:26