MvcTest中为Keycloak加载自定义SecurityCo

MvcTest中为Keycloak加载自定义SecurityCo

本文介绍了NPE在WebMvcTest中为Keycloak加载自定义SecurityConfig时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在webapp本身中,所有内容运行都没有任何问题.身份验证按预期方式工作.但是,由于我在类路径上具有Spring Security,所以现在所有的控制器测试都失败了,因为正在加载默认的Spring Security配置.显然,我希望加载SecurityConfig,因为例如,我配置了csrf是可禁用的,并且默认情况下每个端点都可以在不进行身份验证的情况下进行访问.但是,当我想加载SecurityConfig时,在运行测试时会得到一个NPE.

In the webapp itself everything runs without any problem. The auth works as expected. However, since I have Spring Security on my classpath, all my controller tests are now failing because the default Spring Security configuration is being loaded. Obviously, I want my SecurityConfig to be loaded, because I for example configured that csrf is diabled and that by default every endpoint can be accessed without authentication.But when I want to load my SecurityConfig, I get a NPE when running my test.

我正在通过org.keycloak:keycloak-spring-boot-starterorg.keycloak.bom:keycloak-adapter-bom:9.0.2在Spring Boot应用程序中使用Keycloak适配器.我的Spring Boot版本是2.2.6.RELEASE.

I am using the Keycloak adapters in a Spring Boot application via org.keycloak:keycloak-spring-boot-starter and org.keycloak.bom:keycloak-adapter-bom:9.0.2. My Spring Boot version is 2.2.6.RELEASE.

运行测试时的堆栈跟踪

java.lang.NullPointerException
    at org.keycloak.adapters.KeycloakDeploymentBuilder.internalBuild(KeycloakDeploymentBuilder.java:57)
    at org.keycloak.adapters.KeycloakDeploymentBuilder.build(KeycloakDeploymentBuilder.java:202)
    at org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver.resolve(KeycloakSpringBootConfigResolver.java:39)
    at org.keycloak.adapters.springsecurity.config.KeycloakSpringConfigResolverWrapper.resolve(KeycloakSpringConfigResolverWrapper.java:40)
    at org.keycloak.adapters.AdapterDeploymentContext.resolveDeployment(AdapterDeploymentContext.java:89)
    at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:82)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
    at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
    at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:183)
    at net.my.domain.exampledomain.controller.ExampleControllerTest.givenExampleRouteURIWithAcceptApplicationXml_whenMockMVC_thenVerifyResponse(ExampleControllerTest.java:43)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)

SecurityConfig

@KeycloakConfiguration
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth) {
    KeycloakAuthenticationProvider keycloakAuthenticationProvider =
        keycloakAuthenticationProvider();
    keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
    auth.authenticationProvider(keycloakAuthenticationProvider);
  }

  @Bean
  public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
    return new KeycloakSpringBootConfigResolver();
  }

  @Bean
  @Override
  protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
    return new NullAuthenticatedSessionStrategy();
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    super.configure(http);
    http.csrf().disable().authorizeRequests().anyRequest().permitAll();
  }
}

ExampleControllerTest

@RunWith(SpringRunner.class)
@WebMvcTest(ExampleController.class)
@ContextConfiguration(classes = {ExampleController.class, SecurityConfig.class})
public class ExampleControllerTest {

  @Autowired private MockMvc mockMvc;

  @Test
  public void givenExampleRouteURIWithAcceptApplicationXml_whenMockMVC_thenVerifyResponse()
          throws Exception {
    this.mockMvc
            .perform(MockMvcRequestBuilders.get("/exampleroute").accept(MediaType.APPLICATION_XML))
            .andExpect(status().isOk());
  }
}

推荐答案

这与9.0.1有所不同(尽管我猜您只能从9.0.2开始看到它,因为9.0.1是丢失既来自JBoss存储库又来自Maven Central回购).这将在11.0( KEYCLOAK-14520 中修复.同时,您可以通过以下方式解决此问题:

This is something that broke with 9.0.1 (though I guess you'd only see it starting from 9.0.2, since 9.0.1 is missing from both the JBoss repo and Maven Central repo). This will be fixed in 11.0 (KEYCLOAK-14520). In the mean time, you can workaround by

  1. 删除通过9.0.0所需的KeycloakSpringBootConfigResolver bean
  2. 添加Jira中提到的解决方法
  1. Delete your KeycloakSpringBootConfigResolver bean that was required through 9.0.0
  2. Add the workaround mentioned in the Jira
@Configuration
public class SpringBootKeycloakConfigResolver implements KeycloakConfigResolver {
    private KeycloakDeployment keycloakDeployment;
    private AdapterConfig adapterConfig;

    @Autowired
    public SpringBootKeycloakConfigResolver(AdapterConfig adapterConfig) {
        this.adapterConfig = adapterConfig;
    }

    @Override
    public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
        if (keycloakDeployment != null) {
            return keycloakDeployment;
        }
        keycloakDeployment = KeycloakDeploymentBuilder.build(adapterConfig);
        return keycloakDeployment;
    }
}

这篇关于NPE在WebMvcTest中为Keycloak加载自定义SecurityConfig时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-24 22:08