我想解决的问题: 对于每次对服务的调用,我想检查令牌是否处于活动状态 - 如果它处于非活动状态,我想将用户重定向到登录页面。
当前设置: Grails 3.2.9, Keycloak 3.4.3
到目前为止的想法: 这篇文章看起来很有希望:https://www.linkedin.com/pulse/json-web-token-jwt-spring-security-real-world-example-boris-trivic
在我的安全配置中,我添加了一个令牌过滤器
@Bean
public TokenAuthenticationFilter authenticationTokenFilter() throws Exception {
return new TokenAuthenticationFilter();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure http
http
.addFilterBefore(authenticationTokenFilter(), BasicAuthenticationFilter.class)
.logout()
.logoutSuccessUrl("/sso/login") // Override Keycloak's default '/'
.and()
.authorizeRequests()
.antMatchers("/assets/*").permitAll()
.anyRequest().hasAnyAuthority("ROLE_ADMIN")
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
My TokenAuthenticationFilter目前只打印出请求标题:
公共类TokenAuthenticationFilter扩展了OncePerRequestFilter {
private String getToken( HttpServletRequest request ) {
Enumeration headerEnumeration = request.getHeaderNames();
while (headerEnumeration.hasMoreElements()) {
println "${ headerEnumeration.nextElement()}"
}
return null;
}
@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
String authToken = getToken( request );
}
}
返回:
我想在过滤器中实现的代码/逻辑类似于:
KeycloakAuthenticationToken token = SecurityContextHolder.context?.authentication
RefreshableKeycloakSecurityContext context = token.getCredentials()
if(!context.isActive()){
// send the user to the login page
}
然而,我失去了如何到达那里。 任何帮助非常感谢
答案 0 :(得分:3)
据我了解,您的问题是“如何检查令牌是否有效?”而不是“如何将用户重定向到登录页面?”。
我看到你添加了标签“spring-boot”和“keycloak”,你可以使用“Keycloak Spring Boot Adapter”。假设您使用的是Keycloak版本3.4(v4.0仍处于测试版),您可以找到一些文档here。
如果您不能(或不想)使用Spring Boot Adapter,那么KeycloakSecurityContextRequestFilter
source code的部分可能对您的案例很有用:
KeycloakSecurityContext keycloakSecurityContext = getKeycloakPrincipal();
if (keycloakSecurityContext instanceof RefreshableKeycloakSecurityContext) {
RefreshableKeycloakSecurityContext refreshableSecurityContext = (RefreshableKeycloakSecurityContext) keycloakSecurityContext;
if (refreshableSecurityContext.isActive()) {
...
} else {
...
}
}
这里是getKeycloakPrincipal方法的(Java)source code:
private KeycloakSecurityContext getKeycloakPrincipal() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) {
Object principal = authentication.getPrincipal();
if (principal instanceof KeycloakPrincipal) {
return KeycloakPrincipal.class.cast(principal).getKeycloakSecurityContext();
}
}
return null;
}
如果您想了解如何在SecurityContextHolder中设置身份验证,请阅读KeycloakAuthenticationProcessingFilter
中的piece of (Java) code:
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
if (authResult instanceof KeycloakAuthenticationToken && ((KeycloakAuthenticationToken) authResult).isInteractive()) {
super.successfulAuthentication(request, response, chain, authResult);
return;
}
...
SecurityContextHolder.getContext().setAuthentication(authResult);
...
try {
chain.doFilter(request, response);
} finally {
SecurityContextHolder.clearContext();
}
}
作为替代方案,您还可以检查此动态的github存储库: https://github.com/dynamind/grails3-spring-security-keycloak-minimal
希望能有所帮助
最好的问候,
Jocker。