spring 使用'@PreAuthorize'和'WebTestClient'无法解析视图”

f3temu5u  于 2022-10-30  发布在  Spring
关注(0)|答案(1)|浏览(241)

我在一次测试中遇到了这个奇怪的bug。我的控制器有以下方法:

  1. @Operation(
  2. summary = "Add a new quote",
  3. operationId = "v1AddQuote",
  4. description = "",
  5. responses = [
  6. ApiResponse(responseCode = "201", description = "Created")
  7. ]
  8. )
  9. @RequestMapping(
  10. method = [RequestMethod.POST],
  11. value = ["/quote"],
  12. consumes = ["application/json"]
  13. )
  14. @PreAuthorize("hasRole('ADMIN')")
  15. suspend fun v1AddQuote(quoteDto: QuoteDto): ResponseEntity<Unit> {
  16. val entity = quoteRepository.insert(quoteMapper.dtoToEntity(quoteDto))
  17. .awaitSingleOrNull() ?: return ResponseEntity.internalServerError().build()
  18. return ResponseEntity.created(URI.create("/quote/${entity.id}")).build()
  19. }

我正在使用WebTestClient进行测试:

  1. webClient
  2. .mutateWith(mockUser().roles("ADMIN"))
  3. .post()
  4. .uri("/quote")
  5. .contentType(MediaType.APPLICATION_JSON)
  6. .body(Mono.just(dto), QuoteDto::class.java)
  7. .exchange()
  8. .expectStatus()
  9. .isCreated
  10. .expectHeader()
  11. .location("/quote/${entity.id}")

令人惊讶的是,这会失败:

  1. java.lang.IllegalStateException: Could not resolve view with name 'quote'

这是从哪里来的?一些细节:

  • 在已部署的应用程序中执行相同的请求时不会发生这种情况,只有在测试中才会发生
  • 只需删除@PreAuthorize即可解决此问题
  • 控制器方法实际运行,运行后出现错误

查看堆栈跟踪,我认为这是Spring Security做的某种重定向?

  1. * __checkpoint Handler jdk.proxy2.$Proxy126#v1AddQuote(QuoteDto, Continuation) [DispatcherHandler]
  2. *__checkpoint org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]
  3. *__checkpoint org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter [DefaultWebFilterChain]
  4. *__checkpoint org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter [DefaultWebFilterChain]
  5. *__checkpoint org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain]
  6. *__checkpoint org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
  7. *__checkpoint org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
  8. *__checkpoint org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
  9. *__checkpoint org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
  10. *__checkpoint org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers$MutatorFilter [DefaultWebFilterChain]
  11. *__checkpoint org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers$SetupMutatorFilter [DefaultWebFilterChain]
  12. *__checkpoint HTTP POST "/quote" [ExceptionHandlingWebHandler]

如果有必要,我的Spring Security配置是:

  1. @Configuration
  2. @EnableWebFluxSecurity
  3. @EnableReactiveMethodSecurity
  4. class WebFluxSecurityConfig {
  5. @Bean
  6. fun userDetailsService(): ReactiveUserDetailsService {
  7. val userDetails = User.withDefaultPasswordEncoder()
  8. .username("admin")
  9. .password("admin")
  10. .roles("ADMIN")
  11. .build()
  12. return MapReactiveUserDetailsService(userDetails)
  13. }
  14. @Bean
  15. fun springSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  16. return http.invoke {
  17. authorizeExchange {
  18. authorize(anyExchange, permitAll)
  19. }
  20. csrf { disable() }
  21. httpBasic { }
  22. formLogin { disable() }
  23. logout { disable() }
  24. }
  25. }
  26. }
h22fl7wq

h22fl7wq1#

这个问题实际上与我在帖子中给出的任何信息都没有关系,实际上它几乎完全是偶然解决的。问题是我在我的控制器中继承了一个OpenAPI生成的接口。我不知道为什么会出现这样一个奇怪的错误,但解决方案显然是将此添加到您的安全@EnableReactiveMethodSecurity注解中:

  1. @EnableReactiveMethodSecurity(proxyTargetClass = true)

如果没有proxyTargetClass = true参数,东西会以奇怪的方式断裂。

相关问题