我最近在我的Primefaces Spring-Boot Web应用程序中实现了Keycloak。 这一切都很有效,除了一件事:在“访问令牌生命周期”下的密钥泄露中设置的任何内容之后,Ajax请求“超时”。没有重定向。 ajaxStatus永远不会结束,用户被迫重新加载页面。看看请求,我回来了401“未经授权”。
E.g。用户加载站点并执行他想做的任何事情。在没有重新加载或导航到另一个页面的5分钟后,ajax请求被未经授权。
所以我的问题是:在这种情况下最好的做法是什么,这甚至是预期的行为?
我看到以下选项:
这是我的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.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
答案 0 :(得分:0)
由于Spring Security Adapter使用网络会话,我建议您采取两个步骤(您至少需要实施第二步):
<强> 1。增加领域的KC会话超时:
这表示会话将持续多长时间进行访问(处理刷新令牌的生命周期)。此值与您希望让用户无需再次验证自己的程度有关。
不建议增加访问令牌寿命,因为可以拦截一个令牌的攻击者将有更宽的时间窗口来执行有效的操作。
<强> 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
发送重定向。