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

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

我在一次测试中遇到了这个奇怪的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() }
        }
    }
}
h22fl7wq

h22fl7wq1#

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

@EnableReactiveMethodSecurity(proxyTargetClass = true)

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

相关问题