Sergey
Sergey

Reputation: 963

Spring security redirect when maximum sessions for this principal exceeded

So user login -> closes the browser -> opens browser one more time -> error appears:

HTTP Status 401 - Authentication Failed: Maximum sessions of 1 for this principal exceeded

What I need is to capture this event that session is invalid, remove all sessions for this user and redirect to normal login page

spring security config:

        <http auto-config="true" use-expressions="true">
                <session-management session-fixation-protection="migrateSession">
                    <concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/>
                </session-management>   
                <intercept-url pattern="/login" access="hasRole('ROLE_ANONYMOUS')" requires-channel="any"/> 

    <!--<custom-filter after="CONCURRENT_SESSION_FILTER" ref="sessionExpiration" /> -->
    <!-- .... -->

        </http>

<beans:bean id="sessionExpiration" class="com.test.security.SessionExpirationFilter">
    <beans:property name="expiredUrl">
            <beans:value>/login</beans:value>
        </beans:property>
 </beans:bean>

I tried to implement some filter, but it always shows that session is null:

public class SessionExpirationFilter implements Filter, InitializingBean {
    private String expiredUrl;

    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        String path = httpRequest.getServletPath();
        HttpSession session = httpRequest.getSession(false);

        System.out.println(session);
        if (session == null && !httpRequest.isRequestedSessionIdValid()) {              
            SecurityContextHolder.getContext().setAuthentication(null);
            String targetUrl = httpRequest.getContextPath()
                    + expiredUrl;
            httpResponse.sendRedirect(httpResponse.encodeRedirectURL(targetUrl));
            return;
        }
        chain.doFilter(request, response);
    }

    public void setExpiredUrl(String expiredUrl) {
        this.expiredUrl = expiredUrl;
    }
}

Upvotes: 1

Views: 7840

Answers (4)

Royts
Royts

Reputation: 511

Based on the answers above

Spring security automatically invalidates previous session

if you want to redirect the user on login page, you can add

<session-management invalid-session-url="/login.html">
    ...
</session-management>

Since the previous session is already invalidated.


I have also read in your comment above that you may want to retain the previous session when you try to login again. This defeats your first question, but anyways.

are you talking about 7. Session Fixation Protection with Spring Security

The framework offers protection against typical Session Fixation attacks by configuring what happens to an existing session when the user tries to authenticate again:

<session-management session-fixation-protection="migrateSession">

The corresponding Java configuration:

http.sessionManagement().sessionFixation().migrateSession()

By default, Spring Security has this protection enabled (“migrateSession“) – on authentication a new HTTP Session is created, the old one is invalidated and the attributes from the old session are copied over.

If this is not the desired behavior, two other options are available:

when “none” is set, the original session will not be invalidated

when “newSession” is set, a clean session will be created without any of the attributes from the old session being copied over

Upvotes: 0

真爱国
真爱国

Reputation: 1

<session-management session-authentication-strategy-ref="sas"/>
<beans:bean id="sas" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
        <beans:property name="maximumSessions" value="1"/>
        <beans:property name="exceptionIfMaximumExceeded" value="true"/>
        <beans:constructor-arg name="sessionRegistry" ref="sessionRegistry"/>
    </beans:bean>
    <beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>

Upvotes: -1

Some Java Guy
Some Java Guy

Reputation: 5118

Setting error-if-maximum-exceeded="false" will allow the second session and invalidate the first one as your max-sessions="1"

If you have max-sessions="2" then it will allow the Nth session also and invalidate all N-2 sessions

<session-management session-fixation-protection="migrateSession">
    <concurrency-control max-sessions="1" error-if-maximum-exceeded="false"/>
</session-management> 

Setting error-if-maximum-exceeded="true" will NOT allow the second session and invalidate the second session as your max-sessions="1"

If you have max-sessions="2" then it will not allow the 2+ sessions and invalidate.

Upvotes: 2

Adisesha
Adisesha

Reputation: 5258

From what I understood, you want to invalidate the previous session if it User's session exceeds 'max-sessions'. Set the property 'error-if-maximum-exceeded' to false. Spring security automatically invalidates previous session.

If you are trying to do something different,

  1. Extend ConcurrentSessionControlStrategy class, and override 'allowableSessionsExceeded' method.
  2. Specify the bean reference of the above as 'session-authentication-strategy-ref' attribute value of 'session-management'

.

Upvotes: 6

Related Questions