我在一次测试中遇到了这个奇怪的bug。我的控制器有以下方法:
@Operation(
summary = "Add a new quote",
operationId = "v1AddQuote",
description = "",
responses = [
ApiResponse(responseCode = "201", description = "Created")
]
)
@RequestMapping(
method = [RequestMethod.POST],
value = ["/quote"],
consumes = ["application/json"]
)
@PreAuthorize("hasRole('ADMIN')")
suspend fun v1AddQuote(quoteDto: QuoteDto): ResponseEntity<Unit> {
val entity = quoteRepository.insert(quoteMapper.dtoToEntity(quoteDto))
.awaitSingleOrNull() ?: return ResponseEntity.internalServerError().build()
return ResponseEntity.created(URI.create("/quote/${entity.id}")).build()
}
我正在使用WebTestClient
进行测试:
webClient
.mutateWith(mockUser().roles("ADMIN"))
.post()
.uri("/quote")
.contentType(MediaType.APPLICATION_JSON)
.body(Mono.just(dto), QuoteDto::class.java)
.exchange()
.expectStatus()
.isCreated
.expectHeader()
.location("/quote/${entity.id}")
令人惊讶的是,这会失败:
java.lang.IllegalStateException: Could not resolve view with name 'quote'
这是从哪里来的?一些细节:
- 在已部署的应用程序中执行相同的请求时不会发生这种情况,只有在测试中才会发生
- 只需删除
@PreAuthorize
即可解决此问题 - 控制器方法实际运行,运行后出现错误
查看堆栈跟踪,我认为这是Spring Security做的某种重定向?
* __checkpoint ⇢ Handler jdk.proxy2.$Proxy126#v1AddQuote(QuoteDto, Continuation) [DispatcherHandler]
*__checkpoint ⇢ org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]
*__checkpoint ⇢ org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter [DefaultWebFilterChain]
*__checkpoint ⇢ org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter [DefaultWebFilterChain]
*__checkpoint ⇢ org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain]
*__checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
*__checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
*__checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
*__checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
*__checkpoint ⇢ org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers$MutatorFilter [DefaultWebFilterChain]
*__checkpoint ⇢ org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers$SetupMutatorFilter [DefaultWebFilterChain]
*__checkpoint ⇢ HTTP POST "/quote" [ExceptionHandlingWebHandler]
如果有必要,我的Spring Security配置是:
@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
class WebFluxSecurityConfig {
@Bean
fun userDetailsService(): ReactiveUserDetailsService {
val userDetails = User.withDefaultPasswordEncoder()
.username("admin")
.password("admin")
.roles("ADMIN")
.build()
return MapReactiveUserDetailsService(userDetails)
}
@Bean
fun springSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http.invoke {
authorizeExchange {
authorize(anyExchange, permitAll)
}
csrf { disable() }
httpBasic { }
formLogin { disable() }
logout { disable() }
}
}
}
1条答案
按热度按时间h22fl7wq1#
这个问题实际上与我在帖子中给出的任何信息都没有关系,实际上它几乎完全是偶然解决的。问题是我在我的控制器中继承了一个OpenAPI生成的接口。我不知道为什么会出现这样一个奇怪的错误,但解决方案显然是将此添加到您的安全
@EnableReactiveMethodSecurity
注解中:如果没有
proxyTargetClass = true
参数,东西会以奇怪的方式断裂。