最近,我们将把自定义JWT过滤器迁移到Auth 0 IDP。
我在这个项目中使用了Spring 2.7.1,WebFlux/Kotlin协程。我创建了a sample project to demo Reactive Spring Security OAuth2 with Auth0 IDP issue。
顺便说一句,我已经维护了一个WebMvc版本来演示Spring Security OAuth2和OAuth 0(更新到Spring 2.7.1),其中the tests are working well。
当我将org.springframework.boot:spring-boot-starter-oauth2-resource-server
添加到我们的项目部门以在后端API中启用OAuth2资源服务器支持时。
但现在所有API端点都受到保护,并返回401或403。
我的安全配置是这样的。
@Bean
fun springWebFilterChain(http: ServerHttpSecurity, reactiveJwtDecoder: ReactiveJwtDecoder): SecurityWebFilterChain =
http {
csrf { disable() }
httpBasic { disable() }
formLogin { disable() }
logout { disable() }
// enable OAuth2 resource server support
oauth2ResourceServer { jwt { jwtDecoder = reactiveJwtDecoder } }
exceptionHandling {
authenticationEntryPoint = problemSupport
accessDeniedHandler = problemSupport
}
authorizeExchange {
authorize(pathMatchers(GET, "/v1/me"), authenticated)
authorize(anyExchange, permitAll)
}
}
测试代码是这样的,检查完整的代码(测试是从其他项目移植来的,我没有添加jwt mock)。
@Test
fun `get all posts`() = runTest {
coEvery { posts.findAll() } returns flowOf(
Post(
id = UUID.randomUUID(),
title = "test title",
content = "test content"
)
)
client.get()
.uri("/posts").accept(MediaType.APPLICATION_JSON)
.exchange()
.expectStatus().isOk
.expectBodyList(Post::class.java).hasSize(1)
coVerify(exactly = 1) { posts.findAll() }
}
将get all posts
端点设置为permitAll
,在打开Powershell时运行curl http://localhost:8080/posts
命令时,运行良好,并在控制台中打印所有帖子。
当运行GET /posts
端点测试时,我从控制台获得以下信息。
2022-07-01 12:45:27.021 DEBUG 14132 --- [ main] o.s.w.r.f.client.ExchangeFunctions : [6144e499] HTTP GET /posts
2022-07-01 12:45:27.069 DEBUG 14132 --- [ parallel-1] o.s.w.s.adapter.HttpWebHandlerAdapter : [26193fe] HTTP GET "/posts"
2022-07-01 12:45:27.108 DEBUG 14132 --- [ parallel-1] .s.s.w.s.u.m.AndServerWebExchangeMatcher : Trying to match using org.springframework.security.web.server.csrf.CsrfWebFilter$DefaultRequireCsrfProtectionMatcher@6fc32403
2022-07-01 12:45:27.110 DEBUG 14132 --- [ parallel-1] .s.s.w.s.u.m.AndServerWebExchangeMatcher : Did not match
2022-07-01 12:45:27.146 DEBUG 14132 --- [ parallel-2] o.s.w.s.s.DefaultWebSessionManager : Created new WebSession.
2022-07-01 12:45:27.151 DEBUG 14132 --- [ parallel-2] o.s.s.w.s.u.m.OrServerWebExchangeMatcher : Trying to match using PathMatcherServerWebExchangeMatcher{pattern='/logout', method=POST}
2022-07-01 12:45:27.151 DEBUG 14132 --- [ parallel-2] athPatternParserServerWebExchangeMatcher : Request 'GET /posts' doesn't match 'POST /logout'
2022-07-01 12:45:27.152 DEBUG 14132 --- [ parallel-2] o.s.s.w.s.u.m.OrServerWebExchangeMatcher : No matches found
2022-07-01 12:45:27.156 DEBUG 14132 --- [ parallel-2] a.DelegatingReactiveAuthorizationManager : Checking authorization on '/posts' using org.springframework.security.authorization.AuthenticatedReactiveAuthorizationManager@66bdd968
2022-07-01 12:45:27.159 DEBUG 14132 --- [ parallel-2] ebSessionServerSecurityContextRepository : No SecurityContext found in WebSession: 'org.springframework.web.server.session.InMemoryWebSessionStore$InMemoryWebSession@529dcf30'
2022-07-01 12:45:27.160 DEBUG 14132 --- [ parallel-2] o.s.s.w.s.a.AuthorizationWebFilter : Authorization failed: Access Denied
2022-07-01 12:45:27.174 DEBUG 14132 --- [ parallel-2] ebSessionServerSecurityContextRepository : No SecurityContext found in WebSession: 'org.springframework.web.server.session.InMemoryWebSessionStore$InMemoryWebSession@529dcf30'
2022-07-01 12:45:27.184 DEBUG 14132 --- [ parallel-2] o.s.w.s.adapter.HttpWebHandlerAdapter : [26193fe] Completed 401 UNAUTHORIZED
2022-07-01 12:45:27.189 DEBUG 14132 --- [ parallel-2] o.s.w.r.f.client.ExchangeFunctions : [6144e499] [609b7bfb] Response 401 UNAUTHORIZED
2022-07-01 12:45:27.207 ERROR 14132 --- [ main] o.s.t.w.reactive.server.ExchangeResult : Request details for assertion failure:
> GET /posts
> WebTestClient-Request-Id: [1]
> Accept: [application/json]
No content
< 401 UNAUTHORIZED Unauthorized
< WWW-Authenticate: [Bearer]
< Cache-Control: [no-cache, no-store, max-age=0, must-revalidate]
< Pragma: [no-cache]
< Expires: [0]
< X-Content-Type-Options: [nosniff]
< X-Frame-Options: [DENY]
< X-XSS-Protection: [1 ; mode=block]
< Referrer-Policy: [no-referrer]
0 bytes of content (unknown content-type).
java.lang.AssertionError: Status expected:<200 OK> but was:<401 UNAUTHORIZED>
Expected :200 OK
Actual :401 UNAUTHORIZED
<Click to see difference>
我已将日志记录级别设置为TRACE
,但没有日志来检查我们的路径匹配器规则。它似乎不检查authorizeRequest中的路径匹配器。
我已经将disabled
设置为crsf
,但是crsf过滤器仍然参与安全检查进程,它也累到匹配/logout
的url。
2条答案
按热度按时间ecbunoof1#
@WebfluxTest / @WebmvcTest加载了很少配置。我确实导入了我的Web安全配置,就像您在答案中所做的那样。
您可能希望对控制器端点的生产安全规则进行单元测试。如果是这样,请导入常规安全配置(而不是permitAll()测试配置),并使用以下任一项配置安全上下文:
jwt()
WebTestClient变异器/ WebMvc后处理器@WithMockJwtAuth
k4emjkb12#
看起来
WebFluxTest
注解测试没有扫描项目中我的自定义SecurityConfig
(这是一个简单的配置,没有扩展XXXSecurityConfigurerAdapater),而是使用Sping Boot 内置的默认安全配置。目前,我必须显式添加
SecurityConfig
,以便在测试中启用它。我不确定这是最初的设计目的还是其他原因。