单次注销在 keycloak 和 spring security 中不起作用

Posted

技术标签:

【中文标题】单次注销在 keycloak 和 spring security 中不起作用【英文标题】:Single Log Out not working in keycloak and spring security 【发布时间】:2018-06-23 08:26:42 【问题描述】:

我正在使用 keycloak 服务器及其 spring 安全适配器来保护两个示例应用程序。一切正常,除了没有开箱即用的单一注销解决方案。有什么具体的配置吗?编辑 这是我的注销按钮:

    <c:url var="logoutUrl" value="/sso/logout"/>
    <form class="form-inline" action="$logoutUrl" method="post">
        <input type="submit" value="Log out" />
        <input type="hidden" name="$_csrf.parameterName" value="$_csrf.token"/>
    </form>   

这是我的 spring-security 配置文件:

    <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:sec="http://www.springframework.org/schema/security"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/security
       http://www.springframework.org/schema/security/spring-security.xsd">

    <context:component-scan base-package="org.keycloak.adapters.springsecurity" />

    <sec:authentication-manager alias="authenticationManager">
        <sec:authentication-provider ref="keycloakAuthenticationProvider" />
    </sec:authentication-manager>

    <sec:http auto-config="false" entry-point-ref="keycloakAuthenticationEntryPoint">
        <sec:custom-filter ref="keycloakPreAuthActionsFilter" before="LOGOUT_FILTER" />
        <sec:custom-filter ref="keycloakAuthenticationProcessingFilter" before="FORM_LOGIN_FILTER" />
        <sec:intercept-url pattern="/Login.jsp"         access="permitAll()" />
        <sec:intercept-url pattern="/resources/**"      access="permitAll()" />
        <sec:intercept-url pattern="/Index.jsp"         access="hasRole('ROLE_USER')" />
        <sec:intercept-url pattern="/cont/**"           access="hasRole('ROLE_USER')" />
        <sec:custom-filter ref="logoutFilter" position="LOGOUT_FILTER" />
    </sec:http>

    <bean id="keycloakAuthenticationProvider" class="org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider" />

    <bean id="adapterDeploymentContext" class="org.keycloak.adapters.springsecurity.AdapterDeploymentContextFactoryBean">
        <constructor-arg value="/WEB-INF/keycloak/keycloak.json" />
    </bean>
    <bean id="keycloakAuthenticationEntryPoint" class="org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationEntryPoint" >
        <constructor-arg ref="adapterDeploymentContext"/>
    </bean>

    <bean id="keycloakPreAuthActionsFilter" class="org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter" />
    <bean id="keycloakAuthenticationProcessingFilter" class="org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter">
        <constructor-arg name="authenticationManager" ref="authenticationManager" />
    </bean>

    <bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
        <constructor-arg name="logoutSuccessUrl" value="/Index.jsp" />
        <constructor-arg name="handlers">
            <list>
                <ref bean="keycloakLogoutHandler" />
                <bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
            </list>
        </constructor-arg>
        <property name="logoutRequestMatcher">
            <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
                <constructor-arg name="pattern" value="/sso/logout**" />
                <constructor-arg name="httpMethod" value="POST" />
            </bean>
        </property>
    </bean>
    <bean id="keycloakLogoutHandler" class="org.keycloak.adapters.springsecurity.authentication.KeycloakLogoutHandler">
        <constructor-arg ref="adapterDeploymentContext" />
    </bean>


</beans>

【问题讨论】:

【参考方案1】:

您可以使用 Spring 的注销模式,其余的由 Spring Security 负责。这是一个例子:

    <form method="post" action="logout">
            <input class="logout-input" type="submit" value="Log Out"></> 
            <input type="hidden" name="$_csrf.parameterName" value="$_csrf.token" />
    </form>

【讨论】:

我在帖子中添加了注销按钮和 spring-security 配置文件。无论如何,我还尝试按照您所说的将操作设置为“注销”,但出现此错误:No mapping found for HTTP request with URI [/framework/logout] in DispatcherServlet with name 'mvc-dispatcher

以上是关于单次注销在 keycloak 和 spring security 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

钥匙斗篷 |使用 Spring Security 的 OIDC 反向通道(单)注销

WSO2 和 Spring SAML 单次注销问题

如何在基于 Keycloak/Spring 的应用程序中实现单点注销?

Keycloak 注销不会结束会话

ITfoxtec SAML 2.0 - 单次注销

注销重定向时出现 Keycloak CORS 问题