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
相关产品推荐
相关产品推荐

