使用 Spring Security Adapter 时的 Keycloak 会话超时行为
Posted
技术标签:
【中文标题】使用 Spring Security Adapter 时的 Keycloak 会话超时行为【英文标题】:Keycloak Session Timeout behavior when using Spring Security Adapter 【发布时间】:2018-10-28 16:48:45 【问题描述】:当使用带有 OIDC 客户端协议的 Keycloak 和 Spring Security 时,当 Keycloak SSO 会话超时已经发生时,应用程序会话不会过期。因此,如果用户在访问令牌过期后访问受 Keycloak 适配器保护的应用程序的任何部分,Spring Security 仍然具有身份验证对象。但是,当 Keycloak 适配器检查访问令牌是否处于活动状态(此时它不会处于活动状态)时,适配器(RefreshableKeycloakSecurityContext.java 类)会尝试使用它拥有的刷新令牌来获取新的访问令牌。由于刷新令牌在 Keycloak 中已失效,因此适配器会抛出
Refresh token failure status: 400 "error":"invalid_grant","error_description":"Refresh token expired"
因此,用户仍然可以导航和访问应用程序的任何部分,而无需进入登录页面重新进行身份验证。
任何提示/想法如何实现所需的行为,以便当 Keycloak SSO 会话到期时,用户将被重定向到登录页面并且 Spring 身份验证将失效?
Spring-Security: 4.0.4.RELEASE
Keycloak Spring Security Adapter: 3.4.2.Final
Keycloak Server: 3.4.3.Final
【问题讨论】:
如何部署您的 Web 应用程序?哪个服务器?除了在 KC 中配置的会话超时之外,您是否指定了一些会话超时? @XtremeBiker,感谢您的关注。 Web 应用程序与 Keycloak 分开部署(它在 Tomcat 中运行)。应用程序本身在很大程度上依赖于 JCR 会话(它是一个由 CMS 支持的网站),但在我的安全配置中,我没有明确指定任何会话策略。 Tomcat中是否定义了会话超时配置? @XtremeBiker,不,Tomcat 没有会话超时配置(在 web-app web.xml 和容器 web.xml 中都没有)。在 Java 源代码中搜索硬编码会话超时(例如HttpSession.setMaxInactiveInterval(int)
)也没有找到任何结果。
我找到了您在 3.4.3 中描述的相同功能。 4.3.0 版的行为符合预期。
【参考方案1】:
Keycloak 文档的 xml 配置部分似乎缺少某些内容。有一个过滤器可用于检查令牌并在无法刷新时将用户注销,即 KeycloakSecurityContextRequestFilter。
因此,如果您使用基于文档的 XML 配置,则必须添加以下 bean:
<bean id="keycloakSecurityContextRequestFilter"
class="org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter" />
然后将这个添加到 security:http 配置中:
<security:custom-filter ref="keycloakSecurityContextRequestFilter" after="FORM_LOGIN_FILTER" />
【讨论】:
以上是关于使用 Spring Security Adapter 时的 Keycloak 会话超时行为的主要内容,如果未能解决你的问题,请参考以下文章
仅使用 Spring-Security(或)Spring 进行授权
Spring AMQP 源码分析 07 - MessageListenerAdapter
在使用 Oauth、SAML 和 spring-security 的多租户的情况下从 spring-security.xml 中获取错误
Spring security:Spring security 如何在 SessionRegistry 中注册新会话?
未调用 Spring Security j_spring_security_check
使用 spring-session 和 spring-cloud-security 时,OAuth2ClientContext (spring-security-oauth2) 不会保留在 Redis