【发布时间】:2018-09-30 08:04:18
【问题描述】:
我正在使用带有RouterFunction 的 Spring WebFlux 来定义我的 API 端点。我已经通过以下方式配置了 Spring Security:
@Bean
fun security(httpSecurity: ServerHttpSecurity): SecurityWebFilterChain {
return httpSecurity
.authenticationManager(authenticationManager)
// disable default security
.httpBasic().disable()
.formLogin().disable()
.logout().disable()
.csrf().disable()
.addFilterAt(apiAuthenticationWebFilter(), SecurityWebFiltersOrder.AUTHENTICATION)
.authorizeExchange()
.pathMatchers("/app/health").permitAll()
.pathMatchers("/app/info", "/app/loggers", "/app/metrics").hasAuthority(SecurityRole.SYSTEM)
.anyExchange()
.authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationFailureHandler)
.and()
.build()
}
@Bean
fun securityContextRepository(): NoOpServerSecurityContextRepository {
return NoOpServerSecurityContextRepository.getInstance()
}
private fun apiAuthenticationWebFilter(): AuthenticationWebFilter {
val apiAuthenticationWebFilter = AuthenticationWebFilter(authenticationManager)
apiAuthenticationWebFilter.setAuthenticationFailureHandler(ServerAuthenticationEntryPointFailureHandler(jwtAuthenticationFailureHandler))
apiAuthenticationWebFilter.setAuthenticationConverter(jwtAuthenticationConverter)
apiAuthenticationWebFilter.setRequiresAuthenticationMatcher(PathPatternParserServerWebExchangeMatcher("/**"))
apiAuthenticationWebFilter.setSecurityContextRepository(securityContextRepository())
return apiAuthenticationWebFilter
}
RouterFunction 声明如下:
@Bean
fun apiRouter(testHandler: TestHandler,
errorHandler: ErrorHandler): RouterFunction<*> = router {
(accept(MediaType.APPLICATION_JSON_UTF8).nest {
GET(TEST_PATH, testHandler::test )
})
}.andOther(route(RequestPredicates.all(), HandlerFunction { errorHandler.notFoundResponse() }))
以及处理程序本身:
@Component
class TestHandler(private val testService: TestService) {
fun test(request: ServerRequest): Mono<ServerResponse> {
return request.toMono()
.transform({ testResponse() })
}
问题是request.principal() 始终为空,与ReactiveSecurityContextHolder.getContext().block() 结果相同,但是身份验证配置可以正常工作并验证用户。有趣的一点是,使用带注释的控制器主体声明端点是 not null 并显示正确经过身份验证的用户。
@RestController
class TestController(private val testService: TestService) {
@GetMapping("/test")
fun test(principal: Principal): Mono<String> {
return testService.test().map { message -> message + " " + principal.name }
}
}
是配置错误还是错误?有类似的问题问,也许是同一个问题?
样本:
回购 - https://github.com/yyunikov/spring-boot-2-kotlin-starter/
卷曲示例:
curl -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiJhNjQyMjk0NC01ZDFkLTQxODItOGE2ZS1mZGM0NjEwYzhlNTYiLCJzdWIiOiJ5dW5pa292IiwiaWF0IjoxNTIzNzQyNzcxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvIiwiZW1haWwiOiJ1c2VyQHl1bmlrb3YuY29tIiwicm9sZXMiOlsidXNlciJdfQ.RirM-t7GZnSDQIAn_J-thD1UAzdyxKmiR4ktA_BdlYZsFoYKzy5nj-1dBaG60o7M9FcfwFLAWEe4pc7DplDNjw" localhost:8080/test
【问题讨论】:
-
这可能是 stackoverflow.com/questions/48156572/… 的副本吗?
-
@dmendezg 确实,它似乎通过
flatMap工作,你能解释为什么request.principal().block()返回null 吗?阻塞不应该等待结果可用吗? -
但是平面映射
ReactiveSecurityContextHolder.getContext()仍然没有返回安全对象,为什么会这样?
标签: spring spring-boot spring-security spring-webflux