SessionInformation expiration doesn't lead to

2019-07-10 04:16发布

问题:

I want to have ability to force log out another user if admin want to block it.

I have read following answer

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

I have wrote following code:

@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());
        }
    }
}

I open 2 browsers for (1-admin and 2-user)

I login both.

admin clicks to block user

in debug I get into

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

And see following state:

But after this code execution user still log in in system and can scroll site.

If repeat this operation sessionRegistry.getAllSessions(principal, false)will returns empty list.

Spring-security configuration:

<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>

回答1:

This working:

spring security configuration:

<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>

Inside logout method we set information that session is expired inside sessionRegistry and concurrencyFilter read this and expire http session.

Also I added

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

</listener>

to web.xml