2012-05-03 91 views
3

如果標題不夠清晰,我很抱歉。這裏是細節。會話過期後嘗試註銷導致登錄頁面重定向到登錄頁面

背景

我的工作是使用Spring 3.1.1和Spring 3.1.0安全春基礎的應用。這是我們描述的相關片段:

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

網頁上的「註銷」鏈接指向URL像ROOT-URL/j_spring_security_logout。 因此,點擊這個URL會將我們帶到登錄頁面(login.jsp),並且可以成功登錄。

問題

如果用戶登錄入到應用程序中,等待,直到會話過期,然後嘗試註銷他到達登錄頁面。這可以。然後他鍵入正確的憑據並單擊登錄按鈕。 現在他被重定向到用戶名和密碼字段爲空而不是輸入到應用程序的相同登錄頁面。第二次嘗試登錄成功。

重要提示:只有當用戶之前登錄,會話過期並且他試圖註銷時纔會發生這種情況。例如,如果用戶在會話過期後單擊其他任何鏈接,則不會發生這種情況。在這種情況下,他被重定向到登錄頁面,並可以從第一次嘗試成功登錄。

分析

我的調查顯示如下。 由於SavedRequestAwareAuthenticationSuccessHandler.onAuthenticationSuccess()引起的HTTP重定向,我們兩次到達登錄頁面,並且發生的原因是requestCache包含請求登錄頁面。 requestCacheHttpSessionRequestCache類型的變量,它在會話屬性"SPRING_SECURITY_SAVED_REQUEST"中存儲「緩存」請求。

在正常情況下,此緩存用於重定向到未經身份驗證的用戶在身份驗證後請求的頁面。

但是這裏是我們的情況。 用戶登錄。然後他的會話過期了。然後他點擊鏈接註銷。由於會話過期,用戶被重定向到'j_spring_security_logout',將他重定向到登錄頁面。

某處通過這種方式登錄URL被緩存爲「請求」,所以當用戶登錄時,他被重定向到請求的URL,即登錄頁面。發生重定向時,緩存的URL將被刪除,因此不會發生無限循環;第二次嘗試登錄成功。

下面是相關的代碼參考:

ExceptionTranslationFilter.handleSpringSecurityException() 電話​​(線168)

,做以下兩行(183-184):

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

但在請求的URL這一點是登錄頁面。所以,登錄頁面被緩存。

看起來saveRequest()現在不應該被調用,例如,這味道就像是Spring框架中的一個bug ...

我有解決這個問題的方法,我會在這裏發佈。但是我的解決方案對我來說是一個補丁,所以我希望有人知道「正確」的解決方案。

在此先感謝。

+1

您是否試圖爲'設置'default-target-url'和'always-use-default-target'' ? – lschin

+0

還沒有。我會嘗試。 – AlexR

+0

當會話仍然有效並且您單擊「註銷」時會發生嗎? – jddsantaella

回答

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

沒有理由對登錄頁面本身施加任何限制。

1

試試這個,它爲我工作:

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

替換:

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

由:

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

http.authorizeRequests().anyRequest()認證。 () .and().formLogin() .loginPage( 「/ login.jsf」) .permitAll() .usernameParameter( 「登錄」) .passwordParameter( 「senha」) .defaultSuccessUrl( 「/ paginas /總行/ index.jsf」,真) .failureUrl( 「/ login.jsf無效=真?」);

它適用於我。 (spring-security-web:4.1.3.RELEASE)

相關問題