Spring Security + Keycloak - 如何结合“Access Token Lifespan”

时间:2018-03-16 11:01:07

标签: ajax spring spring-security primefaces keycloak

我最近在我的Primefaces Spring-Boot Web应用程序中实现了Keycloak。 这一切都很有效,除了一件事:在“访问令牌生命周期”下的密钥泄露中设置的任何内容之后,Ajax请求“超时”。没有重定向。 ajaxStatus永远不会结束,用户被迫重新加载页面。看看请求,我回来了401“未经授权”。

E.g。用户加载站点并执行他想做的任何事情。在没有重新加载或导航到另一个页面的5分钟后,ajax请求被未经授权。

所以我的问题是:在这种情况下最好的做法是什么,这甚至是预期的行为?

我看到以下选项:

  1. 增加“Access Token Lifespan”
  2. 如果用户不再被授权,则截取ajax调用并重新加载页面 - >用户放弃了他在网站上做出的可能的输入
  3. 在当前生命周期内刷新每个ajax调用的访问令牌生命周期 - >这甚至可能吗?
  4. 这是我的SpringSecurity和Keycloak配置:

    @Configuration
    @KeycloakConfiguration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(proxyTargetClass = true)
    public class SpringSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
    
    
        private KeycloakClientRequestFactory keycloakClientRequestFactory;
    
        @Inject
        public void setKeycloakClientRequestFactory(KeycloakClientRequestFactory keycloakClientRequestFactory) {
            this.keycloakClientRequestFactory = keycloakClientRequestFactory;
        }
    
        @Inject
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
            SimpleAuthorityMapper grantedAuthorityMapper = new SimpleAuthorityMapper();
            grantedAuthorityMapper.setPrefix("ROLE_");
            grantedAuthorityMapper.setConvertToUpperCase(true);
            keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(grantedAuthorityMapper);
            auth.authenticationProvider(keycloakAuthenticationProvider);
        }
    
        @Bean
        public KeycloakConfigResolver KeycloakConfigResolver() {
            return new KeycloakSpringBootConfigResolver();
        }
    
        @Bean
        @Override
        protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
            return new RegisterSessionAuthenticationStrategy(
                    new SessionRegistryImpl());
        }
    
        @Bean
        public FilterRegistrationBean keycloakAuthenticationProcessingFilterRegistrationBean(
                KeycloakAuthenticationProcessingFilter filter) {
            FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
            registrationBean.setEnabled(true);
            return registrationBean;
        }
    
        @Bean
        public FilterRegistrationBean keycloakPreAuthActionsFilterRegistrationBean(
                KeycloakPreAuthActionsFilter filter) {
            FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
            registrationBean.setEnabled(true);
            return registrationBean;
        }
    
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            super.configure(http);
            http
                    .authorizeRequests()
                        .antMatchers("/resources/**").permitAll()
                        .antMatchers("/javax.faces.resource/**").permitAll()
                        .antMatchers("/pages/accessdenied*").permitAll()
                        .antMatchers("/pages/admin/**").hasRole("ADMIN")
                        .antMatchers("/pages/shared/**").permitAll()
                        .antMatchers("/pages/**").hasRole("ADMIN")
                        .anyRequest().authenticated()
                    .and()
                        .csrf().disable();
        }
    
    
    }
    

    Keycloak设置

    keycloak.enabled=true
    keycloak.auth-server-url=http://host:8090/auth
    keycloak.realm="realm"
    keycloak.public-client=true
    keycloak.resource="client-name"
    keycloak.principal-attribute=preferred_username
    

    Keycloak Client Settings

1 个答案:

答案 0 :(得分:0)

由于Spring Security Adapter使用网络会话,我建议您采取两个步骤(您至少需要实施第二步):

<强> 1。增加领域的KC会话超时:

enter image description here

这表示会话将持续多长时间进行访问(处理刷新令牌的生命周期)。此值与您希望让用户无需再次验证自己的程度有关。

不建议增加访问令牌寿命,因为可以拦截一个令牌的攻击者将有更宽的时间窗口来执行有效的操作。

<强> 2。在您的视图中,控制401例外

即使你有一个持久的会议,仍然会发生401例外。所以你需要在视图方面控制它们。例如,使用AngularJs,在401代码发生的情况下将用户重定向到登录页面的一种非常基本的方法可能是这样的(放入一些拦截器):

function responseError(response) {
    console.log('error: ' + JSON.stringify(response));
    if (!(response.status === 401)) {
        $rootScope.$emit('httpError', response);
    } else {
        //401 error
        window.location.href = window.location.protocol + '//'
                + window.location.host + '/sso/logout';
    }
    return $q.reject(response);
}

对于Primefaces,您最好的可能是在服务器过滤器中实现一些逻辑,如果您的业务逻辑发送401响应,它会向/SSO/logout发送重定向。