2011-02-17 82 views
14

我使用基本HTTP身份驗證對基本LDAP授權的GWT/GXT應用程序進行了改造。當我啓動新的瀏覽器時,它運行良好 - 我得到提示並獲得對公司LDAP的授權。我的問題 - 除非關閉/重新打開瀏覽器,否則我無法註銷。我可以調試,看看SecurityContextLogoutHandler#logout被調用,下面的代碼被執行彈簧安全 - 無法註銷

if (invalidateHttpSession) { 
     HttpSession session = request.getSession(false); 
     if (session != null) { 
      session.invalidate(); 
     } 
    } 

    SecurityContextHolder.clearContext(); 

但是它似乎已經爲網站沒有任何影響被重新加載,除非我重新啓動瀏覽器(甚至清除緩存我再也找不到一個HTTP認證提示/ cookies不會幫助)。這裏的applicationContext.xml的

的相關部分
<security:http auto-config='true'> 
    <security:intercept-url pattern="/reports/**" access="ROLE_USER" /> 
    <security:http-basic /> 
    <security:logout logout-url="/reports/logout" 
       logout-success-url="/reports/Application.html" />  
</security:http> 

我試圖自定義LogoutSuccessHandlerauthentication.setAuthenticated(false);但也沒有效果

任何這裏,我在這裏失蹤?您的幫助將不勝感激

回答

22

好的。花了太多時間在這之後我想我有答案。這很簡單 - 人們不能用服務器端技術拯救基本的HTTP認證。基本上,授權字符串在HTTP頭中被base-64解碼,並且當受保護的頁面被加載到瀏覽器時,安全令牌被重新填充,因此無論您在服務器上擦除它的頻率如何,它在每次調用頁面時都會被複活。我想有可能在瀏覽器端玩一些聰明的技巧,但這將是脆弱和不可靠的

對於我的情況,我將切換到基於表單的身份驗證,它可以更好地控制登錄/註銷過程。

我將就接受贊成的人走出來接受的解決辦法我自己的答案

3

呃......很奇怪。我沒有看到你的配置有什麼問題。您實際上不需要定義任何自定義註銷處理程序,因爲它應該由Spring Security來處理。

試試這個,而不是定義您的logout-url,使用默認的退出鏈接: -

... 
<security:logout logout-success-url="/reports/Application.html" />  
... 

然後,使用/j_spring_security_logout註銷。

這樣工作嗎?

+0

毫不奇怪,這具有相同的效果。正如我所說 - 它通過LogoutHandler邏輯,它只是它看起來什麼都不做 – Bostone 2011-02-17 01:03:33

+0

我的佈線沒有任何問題。事實是 - 基本的HTTP不支持註銷 – Bostone 2011-02-17 18:40:54

0
<logout invalidate-session="true" logout-url="/reports/logout" 
     logout-success-url="/reports/Application.html" /> 

只是將無效會話設置爲'真',看它是否有效。

檢查,如果這個聽者有沒有在你的web.xml:

<!-- Security: to listen session requests --> 
<listener> 
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class> 
</listener> 

如果上面的東西不工作,那麼你可以嘗試以下解決方案。 我認爲問題是在你下面一行,

<security:intercept-url pattern="/reports/**" access="ROLE_USER" /> 

上面一行意味着你添加訪問ROLE_USER到YOUT「/報告/ **」鏈接。 但註銷後,您註銷成功相同​​的網址。那麼它將如何工作? 更改註銷成功頁面的位置,或者您可以在http標籤中添加followin行。

<intercept-url pattern="/reports/Application.html" filters="none" /> 
+0

對不起,你的建議沒有任何工作。 invalidate-session = true是默認情況下,我添加了監聽器和註銷頁面。然而,我認爲註銷頁面是無關緊要的(它是/默認),因爲即使它缺少,因爲我在註銷後立即使用基本的HTTP登錄,我應該用登錄提示命中,這正是沒有發生的事情。我可以逐步執行它所執行的註銷代碼,但它沒有區別。除非我殺了瀏覽器,否則我會保持登錄狀態 – Bostone 2011-02-17 16:37:48

+0

我不知道是誰給了這個解決方案一個積極的數字,但它從根本上說是偏離了觀點。看到我自己的回答 – Bostone 2011-02-17 18:40:01

0

我堅信,你是正確的。您不能在瀏覽器中使其無效而無法使用Basic或摘要式身份驗證。即使在那裏,如果不是不可能的話,也是非常困難的。坦率地說,我甚至無法想出一個辦法來做到這一點(除了試圖關閉瀏覽器)。

正如你提到的,問題是,即使你無效在服務器端的一切,你給它需要自動生成自身的一個新的驗證會話瀏覽器中的一切。清除該問題的唯一方法是清除瀏覽器。即使重新啓動服務器也不會清除禁用瀏覽器創建新身份驗證的能力,這很好地表明您無法在服務器端完成此操作,而不會使Basic或Digest身份驗證合同無效。

坦率地說,這似乎是在瀏覽器中一個相當可觀的安全漏洞,你不應該離開認證與基本或摘要式身份驗證網站後開放訪問服務器上運行的瀏覽器。

形式的認證可能是你最好的選擇,因爲你沒有給如何,除非你允許了rememberMe餅乾復活驗證瀏覽器的信息。即使在那裏,您也可以在註銷時清除cookie,以便更輕鬆。

4

Bostone基本上是正確的,你不能處理這個服務器端。有,但是,a bit of a hack that's available

簡短的答案是將用戶重定向到您希望他們土地上的網址,但有一個錯誤的用戶名,然後@前綴它。因此,作爲一個醜陋的例子,

<security:logout logout-url="/reports/logout" 
    logout-success-url="http://[email protected]/reports/Application.html" /> 

理想情況下,你想實現一個處理程序,會爲你做這個,而是爲了說明,我認爲整個獲取的概念。我發現這樣做

0

一種方法是返回HTTP 401個響應。一些快速測試顯示這適用於Safari的macOS版本,Chrome & Firefox。我使用的代碼基本上是相同的:

@RequestMapping(value="/logout",method=RequestMethod.POST) 
public void logout(HttpServletRequest request, HttpServletResponse response, HttpSession session) { 
    session.setAttribute(LOGOUT_SESSION_KEY, true); 
    response.setStatus(303); 
    response.addHeader("Location", URL_OF_APPLICATION_HOME_PAGE); 
} 

@RequestMapping("/") 
public void home(HttpServletRequest request, HttpServletResponse response, HttpSession session) { 
    if (Boolean.TRUE.equals(session.getAttribute(LOGOUT_SESSION_KEY))) { 
     if (request.getHeader("Authorization") != null) { 
      session.invalidate(); 
     } 

     response.setStatus(401); 
     response.addHeader("WWW-Authenticate", "Basic realm=\"" + HTTP_BASIC_REALM + "\""); 
     return; 
    } 

    /* Generate home page */ 
} 

的技巧是,你通常需要返回401頭兩次 - 第一個後,瀏覽器將其緩存憑據重試(發送「授權」頭,在這一點上我們摧毀用戶的舊會話),第二個似乎清除它們並提示登錄。