【问题标题】:Spring Webflux Security blocking Kafka GET /connectors callsSpring Webflux Security 阻止 Kafka GET /connectors 调用
【发布时间】:2021-10-05 08:55:06
【问题描述】:

我有一个 Spring Boot Webflux 应用程序。我正在将 Kafka 与 Apache camel 一起使用,并且还使用 websockets

我最近添加了Spring security。因为我不需要身份验证,因此我不进行身份验证,而只是授权传入的请求。

由于添加了安全性,它阻止了 Kafka Connect 的 REST API 端点,例如。 GET /connectors call。 IMO,它不应该阻止它们,因为它们会从应用程序内部引发。


错误日志


2021-07-29 22:20:51.654 DEBUG 68377 --- [ctor-http-nio-4] o.s.w.s.adapter.HttpWebHandlerAdapter    : [adf2f930-1, L:/127.0.0.1:8083 - R:/127.0.0.1:60653] HTTP GET "/connectors"
2021-07-29 22:20:51.659 DEBUG 68377 --- [     parallel-3] o.s.w.s.s.DefaultWebSessionManager       : Created new WebSession.
2021-07-29 22:20:51.660 DEBUG 68377 --- [     parallel-3] o.s.s.w.s.u.m.OrServerWebExchangeMatcher : Trying to match using PathMatcherServerWebExchangeMatcher{pattern='/weather-data/api/**', method=GET}
2021-07-29 22:20:51.660 DEBUG 68377 --- [     parallel-3] athPatternParserServerWebExchangeMatcher : Request 'GET /connectors' doesn't match 'GET /weather-data/api/**'
2021-07-29 22:20:51.660 DEBUG 68377 --- [     parallel-3] o.s.s.w.s.u.m.OrServerWebExchangeMatcher : No matches found
2021-07-29 22:20:51.660 DEBUG 68377 --- [     parallel-3] o.s.s.w.s.u.m.OrServerWebExchangeMatcher : Trying to match using PathMatcherServerWebExchangeMatcher{pattern='/weather-data/api/**', method=POST}
2021-07-29 22:20:51.660 DEBUG 68377 --- [     parallel-3] athPatternParserServerWebExchangeMatcher : Request 'GET /connectors' doesn't match 'POST /weather-data/api/**'
2021-07-29 22:20:51.660 DEBUG 68377 --- [     parallel-3] o.s.s.w.s.u.m.OrServerWebExchangeMatcher : No matches found
2021-07-29 22:20:51.660 DEBUG 68377 --- [     parallel-3] o.s.s.w.s.u.m.OrServerWebExchangeMatcher : Trying to match using PathMatcherServerWebExchangeMatcher{pattern='/weather-data/api/events', method=GET}
2021-07-29 22:20:51.660 DEBUG 68377 --- [     parallel-3] athPatternParserServerWebExchangeMatcher : Request 'GET /connectors' doesn't match 'GET /weather-data/api/events'
2021-07-29 22:20:51.660 DEBUG 68377 --- [     parallel-3] o.s.s.w.s.u.m.OrServerWebExchangeMatcher : No matches found
2021-07-29 22:20:51.660 DEBUG 68377 --- [     parallel-3] o.s.s.w.s.a.AuthorizationWebFilter       : Authorization failed: Access Denied
2021-07-29 22:20:51.669  INFO 68377 --- [     parallel-3] c.s.M.w.WebFluxSecurityConfiguration     : Authentication exception

org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: Not Authenticated
    at org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter.commenceAuthentication(ExceptionTranslationWebFilter.java:70) ~[spring-security-web-5.5.0.jar:5.5.0]
    at org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter.lambda$filter$1(ExceptionTranslationWebFilter.java:45) ~[spring-security-web-5.5.0.jar:5.5.0]

1. Webflux 安全配置


package com.reactive.sse.security

import mu.KotlinLogging
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.HttpMethod
import org.springframework.http.HttpStatus
import org.springframework.security.access.AccessDeniedException
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity
import org.springframework.security.config.web.server.SecurityWebFiltersOrder
import org.springframework.security.config.web.server.ServerHttpSecurity
import org.springframework.security.core.AuthenticationException
import org.springframework.security.web.server.SecurityWebFilterChain
import org.springframework.security.web.server.authentication.AuthenticationWebFilter
import org.springframework.security.web.server.authentication.ServerAuthenticationConverter
import org.springframework.web.server.ServerWebExchange
import reactor.core.publisher.Mono


@Configuration
@EnableWebFluxSecurity
class SecurityConfiguration {
    private val logger = KotlinLogging.logger {}

    val READ_ROLE = "DATA_READ"


    @Bean
    fun securityWebFilterChain(
        http: ServerHttpSecurity,
        weatherAuthenticatedRequestManager: WeatherAuthenticatedRequestManager,
        authenticationConverter: ServerAuthenticationConverter
    ): SecurityWebFilterChain {
        val authenticationWebFilter = AuthenticationWebFilter(weatherAuthenticatedRequestManager)
        authenticationWebFilter.setServerAuthenticationConverter(authenticationConverter)

        return http
            .exceptionHandling()
            .authenticationEntryPoint { swe: ServerWebExchange, ex: AuthenticationException? ->
                logger.error(ex) { "Authentication exception" }
                Mono.fromRunnable { swe.response.statusCode = HttpStatus.UNAUTHORIZED }
            }.accessDeniedHandler { swe: ServerWebExchange, ex: AccessDeniedException? ->
                logger.error(ex) { "Authorization exception" }
                Mono.fromRunnable { swe.response.statusCode = HttpStatus.FORBIDDEN }
            }.and()
            .authorizeExchange()
            .pathMatchers(HttpMethod.GET,"/weather-data/api/**").hasRole(READ_ROLE)
            .and()
            .addFilterAt(authenticationWebFilter, SecurityWebFiltersOrder.AUTHENTICATION)
            .httpBasic().disable()
            .csrf().disable()
            .formLogin().disable()
            .logout().disable()
            .build()
    }
}


2. WeatherAuthenticationConverter


package com.reactive.sse.security

import org.springframework.http.HttpCookie
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.Authentication
import org.springframework.security.web.server.authentication.ServerAuthenticationConverter
import org.springframework.stereotype.Component
import org.springframework.web.server.ServerWebExchange
import reactor.core.publisher.Mono


@Component
class WeatherAuthenticationConverter : ServerAuthenticationConverter {

    override fun convert(exchange: ServerWebExchange?): Mono<Authentication> {
        return Mono.justOrEmpty(exchange)
            .flatMap { serverWebExchange: ServerWebExchange ->
                Mono.justOrEmpty(serverWebExchange.request.cookies["X-Auth"])
            }
            .filter { cookies: List<HttpCookie> -> cookies.isNotEmpty() }
            .map { cookies: List<HttpCookie> -> cookies[0].value }
            .map { authenticationStr: String ->
                UsernamePasswordAuthenticationToken(
                    authenticationStr,
                    authenticationStr
                )
            }
    }

}

3. WeatherAuthenticatedRequestManager


package com.reactive.sse.security

import org.springframework.security.authentication.ReactiveAuthenticationManager
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.Authentication
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.stereotype.Component
import reactor.core.publisher.Mono



@Component
class WeatherAuthenticatedRequestManager : ReactiveAuthenticationManager {


    /**
     * Authenticate based on the Jwt token
     *
     * @property authentication
     * @return Authentication Publisher
     */
    override fun authenticate(authentication: Authentication): Mono<Authentication> {
        return Mono.just(authentication)
            .map { authenticationObj: Authentication ->
                val roles: List<String> = (authenticationObj.credentials as List<*>).filterIsInstance<String>()
                val rolesAuthority = roles.map { value -> SimpleGrantedAuthority(value) }
                UsernamePasswordAuthenticationToken(
                    roles,
                    roles,
                    rolesAuthority
                )
            }
    }
}

spring security应该如何配置才不会像这样阻塞内部调用。

【问题讨论】:

    标签: spring-boot spring-security apache-kafka spring-webflux


    【解决方案1】:

    在谷歌之后,我发现 /connectors API 调用由 Kafka 发起。它在端口 8083 上运行。不幸的是,我的 Spring Boot 应用程序在 8083 上运行。因此它被阻止了。我仍然很困惑为什么它会阻止内部调用。

    一旦我将端口更改为 8089 或其他内容,错误就会消失

    【讨论】:

      猜你喜欢
      • 2021-08-17
      • 1970-01-01
      • 2020-04-02
      • 2018-11-03
      • 1970-01-01
      • 1970-01-01
      • 2020-09-18
      • 2019-07-18
      • 2020-04-13
      相关资源
      最近更新 更多