Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring 在Kotlin流中使用ReactiveSecurityContextHolder_Spring_Spring Boot_Kotlin_Spring Webflux_Kotlin Coroutines - Fatal编程技术网

Spring 在Kotlin流中使用ReactiveSecurityContextHolder

Spring 在Kotlin流中使用ReactiveSecurityContextHolder,spring,spring-boot,kotlin,spring-webflux,kotlin-coroutines,Spring,Spring Boot,Kotlin,Spring Webflux,Kotlin Coroutines,我正在使用Kotlin进行SpringBoot(2.2)项目,CouchDB作为(反应式)数据库,结果是异步DAO(挂起函数或返回流的函数)。我试图设置WebFlux,以便也有异步控制器(同样,我希望返回流,而不是Flux)。但是我在从ReactiveSecurityContextHolder检索安全上下文时遇到问题 据我所知,与使用ThreadLocal存储它的SecurityContextHolder不同,ReactiveSecurityContextHolder依赖于这样一个事实,Spri

我正在使用Kotlin进行SpringBoot(2.2)项目,CouchDB作为(反应式)数据库,结果是异步DAO(挂起函数或返回流的函数)。我试图设置WebFlux,以便也有异步控制器(同样,我希望返回流,而不是Flux)。但是我在从
ReactiveSecurityContextHolder
检索安全上下文时遇到问题

据我所知,与使用
ThreadLocal
存储它的
SecurityContextHolder
不同,
ReactiveSecurityContextHolder
依赖于这样一个事实,Spring在订阅我的反应链时,也将该上下文存储在该链中,因此,允许我从链中调用
ReactiveSecurityContextHolder.getContext()

问题是,我必须在某个时候将我的
Mono
转换为流,这使我失去了
SecurityContext
。所以我的问题是:有没有一种方法可以让Spring引导控制器在从我的逻辑中的
ReactiveSecurityContextHolder
检索安全上下文时返回流?基本上,经过简化后,应该是这样的:

@GetMapping
fun getArticles(): Flow<String> {
    return ReactiveSecurityContextHolder.getContext().flux().asFlow() // returns nothing
}
@GetMapping
fun getArticles():流{
return ReactiveSecurityContextHolder.getContext().flux().asFlow()//不返回任何内容
}
请注意,如果我直接返回通量(跳过
.asFlow()
),或者在最后添加
.single()
.toList()
(因此使用
suspend fun
),那么它可以正常工作,并且返回安全上下文,但这不是我想要的。我猜解决方案是将上下文从流量(从
ReactiveSecurityContextHolder
的初始反应链)转移到流,但默认情况下似乎没有这样做


编辑:下面是一个示例项目,展示了这个问题:

您真正想要实现的是从流内部访问您的ReactorContext

实现这一点的一种方法是放松返回流的需要,转而返回通量。这允许您恢复ReactorContext,并将其传递给将用于生成数据的流

@ExperimentalCoroutinesApi
@GetMapping("/flow")
fun flow(): Flux<Map<String, String>> = Mono.subscriberContext().flatMapMany { reactorCtx ->
    flow {
        val ctx = coroutineContext[ReactorContext.Key]?.context?.get<Mono<SecurityContext>>(SecurityContext::class.java)?.asFlow()?.single()
        emit(mapOf("user" to ((ctx?.authentication?.principal as? User)?.username ?: "<NONE>")))
    }.flowOn(reactorCtx.asCoroutineContext()).asFlux()
}
@experimentalRoutinesAPI
@GetMapping(“/flow”)
fun flow():Flux=Mono.subscriberContext().flatMapMany{reactorcx->
流动{
val ctx=coroutineContext[ReactorContext.Key]?.context?.get(SecurityContext::class.java)?.asFlow()?.single()
emit(将(“用户”映射到((ctx?.authentication?.principal as?user?.username?:“”))中)
}.flow(reactorcx.asCoroutineContext()).asFlux()
}
在需要从挂起方法访问ReactorContext的情况下,只需从coroutineContext获取它,无需进一步技巧:

@ExperimentalCoroutinesApi
@GetMapping("/suspend")
suspend fun suspend(): Map<String,String> {
    val ctx = coroutineContext[ReactorContext.Key]?.context?.get<Mono<SecurityContext>>(SecurityContext::class.java)?.asFlow()?.single()
    return mapOf("user" to ((ctx?.authentication?.principal as? User)?.username ?: "<NONE>"))
}
@experimentalRoutinesAPI
@GetMapping(“/suspend”)
suspend fun suspend():映射{
val ctx=coroutineContext[ReactorContext.Key]?.context?.get(SecurityContext::class.java)?.asFlow()?.single()
将mapOf(“用户”返回到((ctx?.authentication?.principal as?user?.username?:“”)
}