【问题标题】:How to unit test a SpringBoot controller secured by keycloak?如何对受 keycloak 保护的 SpringBoot 控制器进行单元测试?
【发布时间】:2020-09-23 16:50:43
【问题描述】:

我知道已经有类似的问题,herehere,关于这个问题,但提出的每个解决方案都未能帮助我。在大多数答案中也提到了this 库,但是(恕我直言)我想避免依赖外部库来测试一个简单的控制器。

所以,我有一个非常简单的 api,可以使用 keycloak 生成的不记名令牌进行访问,我想测试控制器。大致如下:

@Test
@DisplayName("Should be ok")
@WithMockUser
void whenCalled_shouldBeOk() throws Exception {
    SecurityContext context = SecurityContextHolder.getContext();
    Authentication authentication = context.getAuthentication();
    mockMvc.perform(
        post("/api/url/something")
            .content("{}")
            .contentType(APPLICATION_JSON)
            .with(authentication(authentication))
    ).andExpect(status().isOk());
}

问题是我总是会收到KeycloakDeploymentBuilder 抛出的空指针异常,因为它缺少适配器配置。在我们的 SecurityConfig 中,我们扩展了 KeycloakWebSecurityConfigurerAdapter 并为应用程序进行了所有必需的配置,但我未能在测试中模拟/绕过此过程。通常,我会在使用 @WithMockUser 注释的测试中(当不使用 keycloak 时)找到解决此身份验证问题的方法,但这次不是。

是否有办法模拟适配器或过滤器进程以绕过此问题?

我已经尝试了其他问题(图书馆除外)中回答的所有问题,但没有成功。如果您有任何线索可以提供帮助或至少为我指明正确的方向(因为这可能是由于我对弹簧安全性缺乏了解),我们将不胜感激。

【问题讨论】:

  • 不要评论为什么我的回答不能解决你的问题(或接受它......)

标签: java spring-boot keycloak


【解决方案1】:

正如我在回答您链接的第一个问题时已经写的那样,@WithMockUser 在您的代码/conf 可能期望KeycloakAuthenticationToken 时使用UsernamePaswordAuthenticationToken 填充安全上下文。

如果您仔细阅读相同的答案,您会找到使用我的 lib 执行此操作的替代方法:使用 KeycloakAuthenticationToken 实例手动填充安全上下文或在每个测试中模拟。

最小样本与 Mockito I added to my repo:

    @Test
    public void test() {
        final var principal = mock(Principal.class);
        when(principal.getName()).thenReturn("user");

        final var account = mock(OidcKeycloakAccount.class);
        when(account.getRoles()).thenReturn(Set.of("offline_access", "uma_authorization"));
        when(account.getPrincipal()).thenReturn(principal);

        final var authentication = mock(KeycloakAuthenticationToken.class);
        when(authentication.getAccount()).thenReturn(account);

        // post(...).with(authentication(authentication))
        // limits to testing secured @Controller with MockMvc
        // I prefer to set security context directly instead:
        SecurityContextHolder.getContext().setAuthentication(authentication);

        //TODO: invoque mockmvc to test @Controller or test any other type of @Component as usual
    }

也许,在您确定这对您的测试造成了多大影响(此处设置的声明很少)之后,您会重新考虑使用我的库(或从它复制,因为它是开源的)。

使用我的注释,上面的示例变为:

    @Test
    @WithMockKeycloakAuth
    public void test() throws Exception {
        //TODO: invoque mockmvc to test @Controller or test any other type of @Component as usual
    }

关于涉及 Keycloak 的 spring 测试配置,您可以深入了解spring-security-oauth2-test-webmvc-addons 模块的测试。您会找到带有单元测试(和工作测试配置)的complete app using KeycloakAuthenticationToken

【讨论】:

    猜你喜欢
    • 2017-06-24
    • 2010-11-10
    • 2012-04-24
    • 2018-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-17
    • 1970-01-01
    相关资源
    最近更新 更多