java - SessionInformation 过期不会导致用户从系统注销

标签 java spring session spring-security logout

如果管理员想要阻止它,我希望能够强制注销另一个用户。

我已阅读以下答案

How do you log out all logged in users in spring-security?

我写了下面的代码:

@Autowired
private SessionRegistry sessionRegistry;
...
private void logout(String name) {
    System.out.println(name);
    for (Object principal : sessionRegistry.getAllPrincipals()) {
        User user = (User) principal;
        if (user.getUsername().equals(name)) {
            sessionRegistry.getAllSessions(principal, false).stream()
                    .forEach(i -> i.expireNow());
        }
    }
}

我为(1 位管理员和 2 位用户)打开 2 个浏览器

我都登录了。

管理员点击阻止用户

在调试中我进入

if (user.getUsername().equals(name)) {

并看到以下状态: enter image description here

但是在这段代码执行之后用户仍然登录系统并且可以滚动网站。

如果重复此操作 sessionRegistry.getAllSessions(principal, false) 将返回空列表。

Spring 安全配置:

<beans:beans
        xmlns="http://www.springframework.org/schema/security"
        xmlns:beans="http://www.springframework.org/schema/beans"
        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-4.0.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security-3.2.xsd
        ">

    <http auto-config="true" pattern="/admin/**" authentication-manager-ref="adminAuthenticationManager">
        <access-denied-handler error-page="/403" />
        <form-login login-page="/loginAdmin" login-processing-url="/admin/j_spring_security_check_admin"
                    default-target-url="/admin"
                    authentication-failure-url="/loginAdminFailed"
                    authentication-success-handler-ref="authAdminSuccessHandler"/>

        <intercept-url pattern="/admin/j_spring_security_check_admin" access="ROLE_ANONYMOUS"/>
        <intercept-url pattern="/admin/accounts/**" access="ROLE_SUPERADMIN"/>
        <intercept-url pattern="/admin/users/**" access="ROLE_SUPERADMIN"/>
        <intercept-url pattern="/admin/terminals/**" access="ROLE_SUPERADMIN, ROLE_TERMINAL_MODERATOR, ROLE_MODERATOR"/>
        <intercept-url pattern="/admin/money/**" access="ROLE_FINANSIER, ROLE_SUPERADMIN"/>
        <intercept-url pattern="/admin/moderation/**" access="ROLE_SUPERADMIN,ROLE_MODERATOR"/>
        <intercept-url pattern="/admin/moderation/pictures"
                       access="ROLE_SUPERADMIN,ROLE_MODERATOR, ROLE_IMAGE_MODERATOR"/>
        <intercept-url pattern="/admin/statistic/**" access="ROLE_SUPERADMIN"/>
        <intercept-url pattern="/admin/rules/**" access="ROLE_SUPERADMIN"/>
        <intercept-url pattern="/admin/terminals/addImageToTerminal"
                       access="ROLE_SUPERADMIN, ROLE_TERMINAL_MODERATOR, ROLE_MODERATOR"/>
        <intercept-url pattern="/admin/terminals/deleteTerminalImage"
                       access="ROLE_SUPERADMIN, ROLE_TERMINAL_MODERATOR, ROLE_MODERATOR"/>
        <intercept-url pattern="/admin/systemGroupsModeration" access="ROLE_SUPERADMIN"/>
        <intercept-url pattern="/admin/adminUsers" access="ROLE_SUPERADMIN"/>
        <intercept-url pattern="/admin/contentModeration/**" access="ROLE_SUPERADMIN, ROLE_MODERATOR, ROLE_IMAGE_MODERATOR"/>
        <intercept-url pattern="/admin/campaignModeration/**" access="ROLE_SUPERADMIN, ROLE_MODERATOR"/>
        <intercept-url pattern="/admin/monitoring" access="ROLE_SUPERADMIN"/>

        <logout logout-url="/logout" logout-success-url="/loginAdmin"/>
        <port-mappings>
            <port-mapping http="${http.port}" https="${https.port}"/>
        </port-mappings>
        <session-management session-authentication-strategy-ref="sas" invalid-session-url="/invalid-session" />
    </http>    

    <beans:bean id="userSecurityService" class="com.terminal.service.impl.UserSecurityService"/>
    <beans:bean id="authSuccessHandler" class="com.terminal.filter.RoleAuthSuccessHandler"/>

    <beans:bean id="authAdminSuccessHandler" class="com.terminal.filter.admin.RoleAuthAdminHandler"/>
    <beans:bean id="adminSecurityService" class="com.terminal.service.admin.impl.TerminalAdminSecurityServiceImpl"/>

    <beans:bean id="webexpressionHandler"
                class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler"/>

    <authentication-manager id="adminAuthenticationManager">
        <authentication-provider user-service-ref="adminSecurityService">
            <password-encoder ref="encoder"/>
        </authentication-provider>
    </authentication-manager>

    <authentication-manager id="userAuthenticationManager">
        <authentication-provider user-service-ref="userSecurityService">
            <password-encoder ref="encoder"/>
        </authentication-provider>
    </authentication-manager>

    <authentication-manager id="internalUserAuthenticationManager">
        <authentication-provider user-service-ref="userSecurityService">
            <password-encoder ref="noopEncoder"/>
        </authentication-provider>
    </authentication-manager>

    <beans:bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
        <beans:constructor-arg index="0" value="10"/>
    </beans:bean>
    <beans:bean id="noopEncoder" class="org.springframework.security.crypto.password.NoOpPasswordEncoder"/>
    <beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>
    <beans:bean id="sas" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
        <beans:constructor-arg ref="sessionRegistry" />
        <beans:property name="maximumSessions" value="1" />
    </beans:bean>
</beans:beans>

最佳答案

这个工作:

spring 安全配置:

<beans:beans
        xmlns="http://www.springframework.org/schema/security"
        xmlns:beans="http://www.springframework.org/schema/beans"
        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-4.0.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security.xsd">

    <http auto-config="true" pattern="/admin/**" authentication-manager-ref="adminAuthenticationManager">
        <access-denied-handler error-page="/403" />
        <custom-filter ref="concurrencyFilter" after="SECURITY_CONTEXT_FILTER"/>
        <form-login login-page="/loginAdmin" login-processing-url="/admin/j_spring_security_check_admin"
                    default-target-url="/admin"
                    authentication-failure-url="/loginAdminFailed"
                    authentication-success-handler-ref="authAdminSuccessHandler"/>

        <intercept-url pattern="/admin/j_spring_security_check_admin" access="ROLE_ANONYMOUS"/>
        <intercept-url pattern="/admin/accounts/**" access="ROLE_SUPERADMIN"/>
        <intercept-url pattern="/admin/users/**" access="ROLE_SUPERADMIN"/>
        <intercept-url pattern="/admin/terminals/**" access="ROLE_SUPERADMIN, ROLE_TERMINAL_MODERATOR, ROLE_MODERATOR"/>
        <intercept-url pattern="/admin/money/**" access="ROLE_FINANSIER, ROLE_SUPERADMIN"/>
        <intercept-url pattern="/admin/moderation/**" access="ROLE_SUPERADMIN,ROLE_MODERATOR"/>
        <intercept-url pattern="/admin/moderation/pictures"
                       access="ROLE_SUPERADMIN,ROLE_MODERATOR, ROLE_IMAGE_MODERATOR"/>
        <intercept-url pattern="/admin/statistic/**" access="ROLE_SUPERADMIN"/>
        <intercept-url pattern="/admin/rules/**" access="ROLE_SUPERADMIN"/>
        <intercept-url pattern="/admin/terminals/addImageToTerminal"
                       access="ROLE_SUPERADMIN, ROLE_TERMINAL_MODERATOR, ROLE_MODERATOR"/>
        <intercept-url pattern="/admin/terminals/deleteTerminalImage"
                       access="ROLE_SUPERADMIN, ROLE_TERMINAL_MODERATOR, ROLE_MODERATOR"/>
        <intercept-url pattern="/admin/systemGroupsModeration" access="ROLE_SUPERADMIN"/>
        <intercept-url pattern="/admin/adminUsers" access="ROLE_SUPERADMIN"/>
        <intercept-url pattern="/admin/contentModeration/**" access="ROLE_SUPERADMIN, ROLE_MODERATOR, ROLE_IMAGE_MODERATOR"/>
        <intercept-url pattern="/admin/campaignModeration/**" access="ROLE_SUPERADMIN, ROLE_MODERATOR"/>
        <intercept-url pattern="/admin/monitoring" access="ROLE_SUPERADMIN"/>

        <logout logout-url="/logout" logout-success-url="/loginAdmin"/>
        <port-mappings>
            <port-mapping http="${http.port}" https="${https.port}"/>
        </port-mappings>
        <session-management session-authentication-strategy-ref="sas" invalid-session-url="/" />
    </http>


    <beans:bean id="userSecurityService" class="com.terminal.service.impl.UserSecurityService"/>
    <beans:bean id="authSuccessHandler" class="com.terminal.filter.RoleAuthSuccessHandler"/>

    <beans:bean id="authAdminSuccessHandler" class="com.terminal.filter.admin.RoleAuthAdminHandler"/>
    <beans:bean id="adminSecurityService" class="com.terminal.service.admin.impl.TerminalAdminSecurityServiceImpl"/>

    <beans:bean id="webexpressionHandler"
                class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler"/>

    <authentication-manager id="adminAuthenticationManager">
        <authentication-provider user-service-ref="adminSecurityService">
            <password-encoder ref="encoder"/>
        </authentication-provider>
    </authentication-manager>

    <authentication-manager id="userAuthenticationManager">
        <authentication-provider user-service-ref="userSecurityService">
            <password-encoder ref="encoder"/>
        </authentication-provider>
    </authentication-manager>

    <authentication-manager id="internalUserAuthenticationManager">
        <authentication-provider user-service-ref="userSecurityService">
            <password-encoder ref="noopEncoder"/>
        </authentication-provider>
    </authentication-manager>

    <beans:bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
        <beans:constructor-arg index="0" value="10"/>
    </beans:bean>
    <beans:bean id="noopEncoder" class="org.springframework.security.crypto.password.NoOpPasswordEncoder"/>

    <beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>

    <beans:bean id="sas" class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
        <beans:constructor-arg>
            <beans:list>
                <beans:bean class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
                    <beans:constructor-arg ref="sessionRegistry"/>
                    <beans:property name="maximumSessions" value="1" />
                    <beans:property name="exceptionIfMaximumExceeded" value="true" />
                </beans:bean>
                <beans:bean class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy">
                </beans:bean>
                <beans:bean class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
                    <beans:constructor-arg ref="sessionRegistry"/>
                </beans:bean>
            </beans:list>
        </beans:constructor-arg>
    </beans:bean>

    <beans:bean id="concurrencyFilter"
                class="org.springframework.security.web.session.ConcurrentSessionFilter">
        <beans:property name="sessionRegistry" ref="sessionRegistry" />
        <beans:property name="expiredUrl" value="/" />
    </beans:bean>

</beans:beans>

logout 方法中,我们在 sessionRegistry 和 concurrencyFilter 中设置 session 已过期的信息并读取此信息并使 http session 过期。

我也加了

<listener>
        <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>

</listener>

到 web.xml

关于java - SessionInformation 过期不会导致用户从系统注销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32458679/

相关文章:

java - 如何在Android上发送带有进度的短信?

java - 使用 JavaWS 在表单数据中发布文件

java - 使用 Spring Controller 列出数据库中的对象

session - Grails:匿名访问的 CookieTheftException

java - Log4j dailyrollingfileappender 文件问题

spring - 这个 ClientAbortException 是从哪里来的?

java - Spring中如何通过CrudRepository的 `findAll()`方法在序列化中包含回收对象的id?

c# - 在 ASP.NET 中列出字符串 session 变量

session - 如何准确有效地衡量HttpSession大小

java - 在 android 应用程序中读取 mp3 标签