Keycloak spring 适配器 - 检查每个 http 请求的 authToken 是否处于活动状态
Keycloak spring adapter - check that the authToken is active with every http request
我想解决的问题:
每次调用该服务时,我都想检查令牌是否处于活动状态,如果它不活动,我想将用户重定向到登录页面。
Current setup: 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());
}
我的 TokenAuthenticationFilter 目前只打印出请求 headers :
public class TokenAuthenticationFilter extends 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 );
}
}
哪个returns:
- 主机
- user-agent
- 接受
- accept-language
- accept-encoding
- cookie
- 连接
- upgrade-insecure-requests
- cache-control
我想在过滤器中实现的code/logic是这样的:
KeycloakAuthenticationToken token = SecurityContextHolder.context?.authentication
RefreshableKeycloakSecurityContext context = token.getCredentials()
if(!context.isActive()){
// send the user to the login page
}
但是我不知道如何到达那里。
非常感谢任何帮助
据我了解,您的问题是关于 "how to check the token is active?" 而不是 "how to redirect the user to login page?"。
我看到你添加了标签 "spring-boot" 和 "keycloak" 也许你可以使用 "Keycloak Spring Boot Adapter"。假设你使用 Keycloak 的 3.4 版本(v4.0 仍处于测试版),你可以找到一些文档 here.
如果您不能(或不想)使用 Spring 启动适配器,这里是 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 dynamind 存储库:
https://github.com/dynamind/grails3-spring-security-keycloak-minimal
希望能有所帮助。
最好的问候,
乔克.
我想解决的问题:
每次调用该服务时,我都想检查令牌是否处于活动状态,如果它不活动,我想将用户重定向到登录页面。
Current setup: 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());
}
我的 TokenAuthenticationFilter 目前只打印出请求 headers :
public class TokenAuthenticationFilter extends 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 );
}
}
哪个returns:
- 主机
- user-agent
- 接受
- accept-language
- accept-encoding
- cookie
- 连接
- upgrade-insecure-requests
- cache-control
我想在过滤器中实现的code/logic是这样的:
KeycloakAuthenticationToken token = SecurityContextHolder.context?.authentication
RefreshableKeycloakSecurityContext context = token.getCredentials()
if(!context.isActive()){
// send the user to the login page
}
但是我不知道如何到达那里。 非常感谢任何帮助
据我了解,您的问题是关于 "how to check the token is active?" 而不是 "how to redirect the user to login page?"。
我看到你添加了标签 "spring-boot" 和 "keycloak" 也许你可以使用 "Keycloak Spring Boot Adapter"。假设你使用 Keycloak 的 3.4 版本(v4.0 仍处于测试版),你可以找到一些文档 here.
如果您不能(或不想)使用 Spring 启动适配器,这里是 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 dynamind 存储库: https://github.com/dynamind/grails3-spring-security-keycloak-minimal
希望能有所帮助。
最好的问候,
乔克.