-1

我有带有自定义过滤器的 Spring Cloud Gateway。在这个过滤器中,我尝试使用参数调用我的 webclient。来自 ReactiveSecurityContextHolder 的角色。getAccessToken 结果是

com.xy.HeaderGatewayFilter$apply$1$1.apply(HeaderGatewayFilter.kt:37)。

如果我只返回 "getAccessToken(webClient, "fixString" ).flatMap(chain::filter)" 而没有实际角色,它的工作并返回一个 accessToken。

@Component
class HeaderGatewayFilter(@Autowired private val webClient: WebClient) : AbstractGatewayFilterFactory<HeaderGatewayFilter.Config>() {

    open class Config

    override fun apply(config: Config?): GatewayFilter {
        return OrderedGatewayFilter( { exchange, chain ->
           
            return@OrderedGatewayFilter getCurrentUserRole()
                    .map{rolle -> getAccessToken(webClient, rolle )
                    }
                    .map { accessToken ->
                        exchange.request
                                .mutate()
                                .header(HttpHeaders.AUTHORIZATION, "Bearer ${accessToken}")
                        return@map exchange
                    }.flatMap(chain::filter)
           },40)

fun getAccessToken(webClient: WebClient, rolle: String): Mono<String> {
            val map: MultiValueMap<String, String> = LinkedMultiValueMap()
            map.add("scope", "role:${rolle}")
            val inserter = BodyInserters.fromFormData(map)
            return webClient.post().body(inserter).retrieve().bodyToMono(Map::class.java).map {
                   it["access_token"] as String }
        }


    fun  getCurrentUserRole() : Mono<String> {
        return ReactiveSecurityContextHolder.getContext()
                .switchIfEmpty(Mono.error(IllegalStateException("Context is empty")))
                .map(SecurityContext::getAuthentication)
                .map(Authentication::getPrincipal)
                .cast(Jwt::class.java)
                .map {jwt -> 
                    return@map jwt.claims["realm_access"] as JSONObject
                }
                .map { realmAccess ->
                   return@map realmAccess["roles"] as JSONArray}
                .map { rollen -> rollen.first().toString() }
    }
4

1 回答 1

0

好,我知道了。我级联中的所有内容都必须返回一个 Mono。我有一个映射,它返回一个字符串,但现在我将其更改为 Mono

于 2020-11-02T14:30:03.017 回答