繁体   English   中英

Spring RefreshableKeycloakSecurityContext泄漏内存

[英]Spring RefreshableKeycloakSecurityContext Leak Memory

我正在Spring Boot 2.0.3中开发应用程序。 当大量带令牌的REST请求发送到应用程序后,应用程序由于RefreshableKeycloakSecurityContext而导致内存泄漏。 帖子按钮上的照片对此进行了描述。

keycloak依赖项:

    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-spring-boot-2-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-admin-client</artifactId>
        <version>3.4.0.Final</version>
        <type>jar</type>
    </dependency>
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-server-spi</artifactId>
        <version>3.4.3.Final</version>
        <type>jar</type>
    </dependency>
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-events-api</artifactId>
        <version>1.0.2.Final</version>
        <type>jar</type>
    </dependency>

SecurityConfig:

     public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        try {
            KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
            keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
            auth.authenticationProvider(keycloakAuthenticationProvider);
        }catch(Exception ex){
            log.error(ex);
        }
    }

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

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

    @Override
    protected void configure(HttpSecurity http) {
        try {
            super.configure(http);
            http
                    .cors()
                    .configurationSource(corsConfigurationSource())
                    .and()
                    .authorizeRequests()
                    .antMatchers("/api/public/**")
                    .permitAll();
                    http.csrf().disable();
        }catch (Exception ex){
            throw new RuntimeException("Problem podczas uprawnien " + ex);
        }

    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST","PUT","DELETE", "OPTIONS"));
        configuration.setAllowedHeaders(Arrays.asList("Access-Control-Allow-Origin","Origin","Accept,X-Requested-With","Content-Type","Access-Control-Request-Method","Access-Control-Request-Headers","Authorization"));
        configuration.setMaxAge((long)1);
        configuration.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

}

内存泄漏图像

有人可以帮助解决这个问题吗?

问题出在SecurityConfig类中。 你用:

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

在该类中,您可以看到:

public class RegisterSessionAuthenticationStrategy implements SessionAuthenticationStrategy {
private final SessionRegistry sessionRegistry;

public RegisterSessionAuthenticationStrategy(SessionRegistry sessionRegistry) {
    Assert.notNull(sessionRegistry, "The sessionRegistry cannot be null");
    this.sessionRegistry = sessionRegistry;
}

public void onAuthentication(Authentication authentication, HttpServletRequest request, HttpServletResponse response) {
    this.sessionRegistry.registerNewSession(request.getSession().getId(), authentication.getPrincipal());
}

}

编码:

public void onAuthentication(Authentication authentication, HttpServletRequest request, HttpServletResponse response) {
    this.sessionRegistry.registerNewSession(request.getSession().getId(), authentication.getPrincipal());
}

导致您的问题。 您所有的休息都将创造出春季记忆中的会议。 为了避免这种情况,您应该使用:

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

使用SecurityConfig类中的NullAuthenticatedSessionStrategy替换RegisterSessionAuthenticationStrategy。

此举之后,您的应用程序将不再记住该会话。 (检查内存转储前后)。

更多信息在这里: https : //github.com/dynamind/grails3-spring-security-keycloak-minimal/blob/master/README.md

我从未使用过Keycloak,尽管您没有直接实例化RefreshableKeycloakSecurityContext,但也许您不断使用new()连续分配的任何类(例如KeycloakSpringBootConfigResolver)都在每次实例化它。

在这种情况下,如果您不清除指向该对象的所有引用,则不会收集它们的引用。并且您将发生内存泄漏。

您是否已经尝试过使用内存分析工具? 让我向您推荐Eclipse MAT,您应该能够对应用程序进行堆转储并生成内存泄漏报告。 您还可以检查统治者树,以查看谁在保留对泄漏内存的引用。

https://eclipsesource.com/blogs/2013/01/21/10-tips-for-using-the-eclipse-memory-analyzer/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM