简体   繁体   中英

Redirecting to login page after login caused by attempt to logout when session is expired

I am sorry if the title is not clear enough. Here are the details.

Background

I am working on Spring based application that uses Spring 3.1.1 and Spring security 3.1.0. Here is the relevant fragment of our descriptor:

<security:http auto-config='true'>      
    <security:intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <security:intercept-url pattern="/login*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <security:intercept-url pattern="/**" access="ROLE_USER" />     
    <security:form-login login-page='/login' authentication-failure-url="/login?authfailed=true"/>              
</security:http>

The "sign-out" link on the web page refers to URL like ROOT-URL/j_spring_security_logout . So, clicking on this URL brings us to login page ( login.jsp ) and can login again successfully.

Problem

If user logs-in into the application, waits until session is expired and then tries to sign-out he arrives to login page. This is fine. Then he types correct credentials and clicks login button. Now he is redirected to the same login page where username and password fields are empty instead of enter to the application. The second attempt to log-in succeeds.

Important: this happens only if the user was logged-in before, the session was expired and he tried to log-out. It does not happens for example if user clicks any other link after session expiration. In this case he is redirected to login page and can successfully login from the first attempt.

Analysis

My investigation showed the following. We arrive to the login page twice due to HTTP redirect caused by SavedRequestAwareAuthenticationSuccessHandler.onAuthenticationSuccess() and happens because requestCache contains request to login page. requestCache is variable of type HttpSessionRequestCache that stores "cached" request in session attribute "SPRING_SECURITY_SAVED_REQUEST" .

In normal situation this cache is used for redirecting to page requested by not-authenticated user after his authentication.

But here is what happens in our case. The user logs-in. Then his session is expired. Then he clicks link to log-out. Since session is expired user is redirected to 'j_spring_security_logout' that redirects him to login page.

Somewhere on this way the login URL is cached as "requested", so when user logs in he is redirected to requested URL, ie to login page. When redirect happens the cached URL is removed, so infinite loop does not happen; second attempt to log-in succeeds.

Here are the relevant code reference:

ExceptionTranslationFilter.handleSpringSecurityException() calls sendStartAuthentication() (line 168)

that does the following (lines 183-184):

    SecurityContextHolder.getContext().setAuthentication(null);
    requestCache.saveRequest(request, response);

But the requested URL at this point is login page. So, the login page is cached.

It looks like the saveRequest() just should not be called at this point, eg this smells as a bug in Spring framework...

I have solution to this problem and I will post it here. But my solution looks as a patch for me, so I hope somebody know the "right" solution.

Thanks in advance.

<intercept-url pattern="/login.jsp*" access="permitAll" />
<intercept-url pattern="/login*" access="permitAll" />

No reason to put any constraints on the login-page itself.

Try This, it works for me :

<security:form-login 
        login-page="/login.jsp" 
        default-target-url="/home.jsp"
        always-use-default-target="true" 
        authentication-failure-url="/login?authfailed=true"/>

Replace:

.defaultSuccessUrl("/paginas/geral/index.jsf")

by:

.defaultSuccessUrl("/paginas/geral/index.jsf", true)

http.authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login.jsf") .permitAll() .usernameParameter("login") .passwordParameter("senha") .defaultSuccessUrl("/paginas/geral/index.jsf", true) .failureUrl("/login.jsf?invalid=true");

it works for me. (spring-security-web: 4.1.3.RELEASE)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM