Keycloak注销不会结束会话

时间:2018-03-09 09:44:51

标签: java logout embedded-jetty keycloak

我在使用Spring Framework的Java应用程序中使用Keycloak 3.4,使用Keycloak Jetty-81-Adapter 3.4在Jetty 8.1中使用。

根据Keycloak文档,我应该能够在Java EE应用程序中使用HttpServletRequest从Keycloak注销。但是,这在我的情况下不起作用,即使Jetty支持HttpServletRequests。

  

您可以通过多种方式注销Web应用程序。对于Java EE servlet容器,可以调用HttpServletRequest.logout()..

如果我尝试以这种方式注销,我会被重定向到keycloak(登录屏幕,可以选择多个域登录)。但是,当我选择我喜欢的领域时,我会立即再次登录到web应用程序,而无需提供任何凭据。

我尝试了替代方法,重定向到Keycloak:

  

对于其他浏览器应用程序,您可以将浏览器重定向到
  http://auth-server/auth/realms/ {领域名} /协议/ OpenID的连接/登出?REDIRECT_URI = encodedRedirectUri

但是它会在Keycloak日志中抛出连接拒绝错误,因为Keycloak尝试直接调用我的webapp。它对Keycloak会话没有影响,该会话保持活动状态。我非常希望不需要从Keycloak到webapp直接进行服务器端调用。

为什么HttpServletRequest.logout()在我的情况下不破坏keycloak会话的任何建议? HttpServletRequest的Jetty实现是否与Java EE实现完全不同,它根本无法工作?

3 个答案:

答案 0 :(得分:2)

使用远程(OIDC)身份提供程序时,我有类似的经历。我发现HttpServletRequest.logout确实在Keycloak中破坏了会话,但没有传播到我的远程身份提供者的注销URL。当进入远程登录站点时,它立即将我重新定向回来,看到我有一个活跃的会话。这看起来很像keycloak会话实际上没有失效,但我检查了它。使用浏览器重定向到网址已在两个地方注销。可能是Keycloak中的错误。

你是否面临同样的问题?要验证,请尝试注销,然后在keycloak和列表会话中选择您的客户端,以查看它是否仍存在于Keycloak中。

答案 1 :(得分:0)

您需要将包含“ request.logout()”操作的Servlet或其余部分作为受保护的资源,以便令牌可用:

查看以下文档: “

服务器传递刷新令牌。如果该方法是从 未受保护的页面(不检查有效令牌的页面) 刷新令牌可能不可用,在这种情况下,适配器会跳过 电话。因此,使用受保护的页面执行 建议使用HttpServletRequest.logout(),以便当前令牌 一律考虑在内,并与{project_name}进行互动 服务器将在需要时执行。

答案 2 :(得分:0)

如果从不受保护的页面(不检查有效令牌的页面)执行方法(注销),则刷新令牌可能不可用,在这种情况下,适配器将跳过该调用。因此,建议使用受保护的页面来执行HttpServletRequest.logout(),以便始终考虑当前令牌,并在需要时与Keycloak服务器进行交互。 https://www.keycloak.org/docs/latest/securing_apps/index.html#logout

这在受保护的页面中对我有用,但在不受保护的页面中不起作用

public ExternalContext currentExternalContext() {
        if (FacesContext.getCurrentInstance() == null) {
            throw new RuntimeException("message here ");
        } else {
            return FacesContext.getCurrentInstance().getExternalContext();
         }
    }

public void logout() throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) currentExternalContext().getRequest();
    ExternalContext externalContext = currentExternalContext();
    request.logout();
    externalContext.redirect(externalContext.getRequestContextPath());
}