oauth-2.0 在Spring Boot项目中添加资源服务器时,所有端点在ControllerTest中返回401/403

k75qkfdt  于 2022-10-31  发布在  Spring
关注(0)|答案(2)|浏览(106)

最近,我们将把自定义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。

ecbunoof

ecbunoof1#

@WebfluxTest / @WebmvcTest加载了很少配置。我确实导入了我的Web安全配置,就像您在答案中所做的那样。
您可能希望对控制器端点的生产安全规则进行单元测试。如果是这样,请导入常规安全配置(而不是permitAll()测试配置),并使用以下任一项配置安全上下文:

  • 来自spring-security-test的jwt() WebTestClient变异器/ WebMvc后处理器
  • spring-addons转换为@WithMockJwtAuth
k4emjkb1

k4emjkb12#

看起来WebFluxTest注解测试没有扫描项目中我的自定义SecurityConfig这是一个简单的配置,没有扩展XXXSecurityConfigurerAdapater),而是使用Sping Boot 内置的默认安全配置。
目前,我必须显式添加SecurityConfig,以便在测试中启用它。

class TestsClass{

   @TestConfiguration
   @Import(SecuirtyConfig::class)
   class TestConfig

   //test methods
}

我不确定这是最初的设计目的还是其他原因。

相关问题