получите SecurityContextHolder.getContext().getAuthentication() с помощью настраиваемого распознавателя конфигурации ключа.

#java #spring-boot #keycloak

Вопрос:

У меня есть серверное приложение для нескольких арендаторов, использующее keycloak в качестве поставщика удостоверений личности.

В моих настройках, использующих Java, у меня есть пользовательский решатель конфигурации ключа, в котором я загружаю настройки для развертывания ключа в соответствии с областью каждого клиента, я делаю это через поддомен запроса.

Тогда у каждого арендатора будет поддомен для доступа к интерфейсному приложению, например enterprisea.mydomain.com и enterpriseb.mydomain.com и запрос на серверную часть будет осуществляться с использованием тех же поддоменов, например enterprisea.mydomain.com/api и enterpriseb.mydomain.com/api.

Я хочу изменить этот сценарий, в котором, передавая свой сервер для ответа по URL-адресу, например: back-end-api.mydomain.com и я хотел бы знать, что такое область по маркеру доступа.

У меня есть пользовательский решатель KeyCloakConfigResolver, и я хотел бы изменить его, чтобы получить значение области по маркеру доступа, но SecurityContextHolder.getContext() оно равно нулю, и я не могу определить причину.

 public class KeyCloakConfigResolver implements KeycloakConfigResolver {

@Override
    public KeycloakDeployment resolve(HttpFacade.Request request) {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
       
               ... SecurityContextHolder.getContext() -- NullPointerException
    }
}
 

Устройство для настройки ключа

 @Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class KeycloakConfigAdapter extends KeycloakWebSecurityConfigurerAdapter {

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

    @Override
    protected AuthenticationEntryPoint authenticationEntryPoint() throws Exception {
        return new MultitenantKeycloakAuthenticationEntryPoint(adapterDeploymentContext());
    }

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

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

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration =  new CorsConfiguration().applyPermitDefaultValues();
        configuration.addAllowedOriginPattern("*");
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
        configuration.setAllowedHeaders(Arrays.asList("X-Requested-With", "Origin", "Content-Type", "Accept", "Authorization"));
        configuration.addAllowedHeader("*");
        configuration.setAllowCredentials(true);
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.sessionManagement()
            .sessionAuthenticationStrategy(sessionAuthenticationStrategy())
            .and().addFilterBefore(keycloakPreAuthActionsFilter(), LogoutFilter.class)
            .addFilterBefore(keycloakAuthenticationProcessingFilter(), X509AuthenticationFilter.class).exceptionHandling()
            .authenticationEntryPoint(authenticationEntryPoint())
            .and().logout().addLogoutHandler(keycloakLogoutHandler()).logoutUrl("/logout")
            .logoutSuccessHandler((HttpServletRequest request, HttpServletResponse response, Authentication authentication)
                    -> response.setStatus(HttpServletResponse.SC_OK))
            .and().apply(new SpringKeycloakSecurityAdapter());

    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/v2/api-docs",
                "/configuration/ui",
                "/swagger-resources/**",
                "/configuration/security",
                "/swagger-ui.html",
                "/webjars/**");
    }

    public static class SpringKeycloakSecurityAdapter extends AbstractHttpConfigurer<SpringKeycloakSecurityAdapter, HttpSecurity> {

        @Override
        public void init(HttpSecurity http) throws Exception {
            http.csrf().disable();
            http.authorizeRequests()
                    .antMatchers("/logout", "/", "/unsecured").permitAll()
                    .anyRequest().authenticated();

        }
    }
}
 

ApiBackEndApplication

 @SpringBootApplication
public class ApiBackEndApplication {

    public static void main(String[] args) {
        SpringApplication.run(ApiBackEndApplication.class, args);
    }

    @Bean
    @ConditionalOnMissingBean(KeyCloakConfigResolver.class)
    public KeycloakConfigResolver keycloakConfigResolver() {
        return new KeyCloakConfigResolver();
    }
}