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

Ktor RSocket客户端无法认证Spring RSocket服务器求助

解决Spring RSocket Security认证下Kotlin Ktor客户端连接问题

问题背景

搭建了Spring RSocket服务器为Kotlin Ktor应用提供实时更新服务,未配置认证时Kotlin客户端可正常连接流并接收更新;但为服务器配置RSocket Spring Security基础认证后,使用Kotlin原生RSocket客户端请求流时抛出io.rsocket.kotlin.RSocketError$Setup$Rejected: Access Denied异常。

原客户端错误实现:

var flow = rSocket.requestStream(buildPayload {
    data(ByteArray(0))
    compositeMetadata {
        add(SimpleAuthMetadata("app", "xrOMMKj2jyaf4vH9RC6w"))
        add(RoutingMetadata("api.v1.messages.events.stream/qQYISR9xcmR8ZtVHNgg1lbYgSQcxafPqPW0ZbE0yaA6ham6n54"))
    }
})

flow.onEach {
    println(it.data.readText())
}.collect()

目前仅能通过引入Spring RSocketRequester依赖实现正常连接,但Ktor应用无法引入Spring依赖,需要纯Kotlin原生依赖的解决方案。

解决方案

问题核心在于:Spring RSocket Security的基础认证是在RSocket连接建立的Setup阶段验证身份,而非请求阶段。原代码错误地将认证元数据放在了请求Payload中,而非SetupPayload里。以下是基于rsocket-kotlin库(Kotlin原生RSocket实现)的正确实现:

1. 确认依赖(Gradle示例)

引入Ktor兼容的RSocket Kotlin依赖:

dependencies {
    implementation("io.rsocket.kotlin:rsocket-kotlin-core:0.16.0")
    implementation("io.rsocket.kotlin:rsocket-kotlin-transport-ktor-client:0.16.0")
    implementation("io.ktor:ktor-client-websockets:2.3.3") // Ktor WebSocket传输依赖
}

2. 正确建立带认证的RSocket连接

在Setup阶段添加认证元数据,匹配Spring Security期望的message/x.rsocket.authentication.v0 MIME类型:

import io.rsocket.kotlin.core.RSocketConnector
import io.rsocket.kotlin.metadata.RoutingMetadata
import io.rsocket.kotlin.metadata.SimpleAuthMetadata
import io.rsocket.kotlin.payload.buildPayload
import io.rsocket.kotlin.transport.ktor.client.websocket
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    // 构建RSocket连接器,在Setup阶段注入认证元数据
    val rSocket = RSocketConnector {
        setupPayload {
            buildPayload {
                data(ByteArray(0))
                // 添加Simple认证元数据,对应Spring的用户名密码认证逻辑
                metadata(SimpleAuthMetadata("app", "xrOMMKj2jyaf4vH9RC6w"))
            }
        }
    }.connect(websocket("ws://localhost:8080/rsocket")).await()

    // 发起流请求,路由元数据放在请求Payload中
    launch {
        val flow = rSocket.requestStream(buildPayload {
            data(ByteArray(0))
            compositeMetadata {
                add(RoutingMetadata("api.v1.messages.events.stream/qQYISR9xcmR8ZtVHNgg1lbYgSQcxafPqPW0ZbE0yaA6ham6n54"))
            }
        })

        flow.onEach { payload ->
            println(payload.data.readText())
        }.collect()
    }
}

3. 关键说明

  • 认证时机:Spring RSocket Security仅在连接初始化的Setup阶段校验身份,因此必须将SimpleAuthMetadata放在SetupPayload中,而非请求阶段的Payload里。
  • 元数据兼容性:SimpleAuthMetadata对应RSocket标准的Simple Authentication协议,与Spring Security的UsernamePasswordMetadata序列化格式完全兼容,无需额外编码器。
  • Ktor集成:使用rsocket-kotlin-transport-ktor-client可以无缝与Ktor应用集成,完全不需要引入Spring相关依赖。

内容的提问来源于stack exchange,提问作者Vinícius M. Freitas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 14:15:41