2010-04-09 109 views
6

我使用Spring Security的RememberMe服務來保持用戶身份驗證。Spring安全記憶服務會話Cookie

我想找一個簡單的方法將RememberMe cookie設置爲會話cookie而不是固定的到期時間。對於我的應用程序,cookie應該保持到用戶關閉瀏覽器。

關於如何最好地實現這一點的任何建議?對此有任何擔憂是潛在的安全問題?

這樣做的主要原因是,使用基於cookie的令牌時,負載均衡器後面的任何服務器都可以爲受保護的請求提供服務,而不依賴於用戶的身份驗證以存儲在HttpSession中。實際上,我明確地告訴Spring Security永遠不要使用名稱空間創建會話。此外,我們正在使用Amazon的Elastic Load Balancing,因此不支持粘性會話。

注意:儘管我知道,截至2008年4月,亞馬遜現在支持粘性會話,但我仍然不希望將其用於少數其他原因。即一臺服務器不合時宜的消亡仍然會導致與其相關的所有用戶的會話丟失。 http://aws.amazon.com/about-aws/whats-new/2010/04/08/support-for-session-stickiness-in-elastic-load-balancing/

+0

爲什麼你不是簡單地實現自己的RememberMe實現嗎?這很容易。 – lexicore 2010-04-09 14:58:59

+0

重複? http://chackoverflow.com/questions/2594960/best-practice-to-implement-secure-remember-me – rook 2010-04-09 15:20:32

+0

@lexicore人員實施他們自己的會話可能會給您的網絡應用帶來真正的破壞。不要重新發明風團。閱讀我的帖子上的「重複?」上面的問題。 – rook 2010-04-09 15:21:44

回答

3

要使會話正常工作與負載平衡我會讓你的會話數據存儲在sql數據庫。

該Cookie應該始終是一個過期的隨機值。在某些情況下,您可以將狀態存儲爲Cookie值,並且不會造成安全隱患,例如用戶首選的語言,但應儘可能避免這種情況。打開HttpOnlyCookies,是一個好主意。

閱讀A3:2010年OWASP前10名中的「破壞的身份驗證和會話管理」。本節中重要的一點是,必須將HTTPS用於整個會話。如果會議持續很長時間,那麼這更重要。

另外請記住,「記住我」創建了一個大型窗口,攻擊者可以在該窗口上「騎」會話。這給了攻擊者很長的時間(幾個月?),他可以提供CSRF攻擊。即使你擁有CSRF保護,攻擊者仍然可以使用XSS和XmlHttpRequest進行會話(HttpOnlyCookies將防止完全劫持)。 「記住我」讓其他威脅如xss,csrf,嗅探更嚴重。只要這些漏洞得到解決,那麼你就不應該對真實世界的黑客有問題。

實現「記住我」功能的最簡單(也是安全的)方法是修改會話超時以使其非常大(幾個月)。如果「記住我」複選框未被選中,則會使用新的超時(登錄後1天)存儲會話變量。請記住,即使cookie在瀏覽器關閉時被刪除,該會話在服務器端仍然處於活動狀態。如果會話ID被盜,那麼它仍然可以使用。

+0

自定義的RememberMe過濾器與在每個請求上創建新令牌相比如何。新的令牌可以具有較短的使用期限,例如20分鐘。如果用戶什麼都不做,令牌就會過期。如果用戶在20分鐘窗口中發出另一個請求,則會創建一個新的20分鐘窗口。如果用戶的會話以某種方式被盜,更改用戶的密碼仍然會使野外任何有效的令牌失效......思考? – 2010-04-14 13:15:46

+0

我記得我之前聽說過這個想法......它需要持久化令牌到數據庫,但不需要HttpSession: http://jaspan.com/improved_persistent_login_cookie_best_practice 也許我會研究在Spring中繼承PersistentTokenBasedRememberMeService安全。 – 2010-04-14 14:07:52

5

Spring Security 3不提供如何生成cookie的配置。你必須覆蓋默認行爲:

import javax.servlet.http.Cookie; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices; 

/** Cookie expires on session. */ 
public class PersistentTokenBasedRememberMeServicesCustom extends 
    PersistentTokenBasedRememberMeServices { 

    /** only needed because super throws exception. */ 
    public PersistentTokenBasedRememberMeServicesCustom() throws Exception { 
    super(); 
    } 

    /** Copy of code of inherited class + setting cookieExpiration, */ 
    @Override 
    protected void setCookie(String[] tokens, int maxAge, 
     HttpServletRequest request, HttpServletResponse response) { 
    String cookieValue = encodeCookie(tokens); 
    Cookie cookie = new Cookie(getCookieName(), cookieValue); 
    //cookie.setMaxAge(maxAge); 
    cookie.setPath("/"); 
    cookie.setSecure(false); // no getter available in super, so always false 

    response.addCookie(cookie); 
    } 
} 

確保,對於您通過添加類名來它是rememberMeService您使用此定製對PersistentTokenBasedRememberMeServices的bean的配置:

<beans:bean id="rememberMeServices" 
class="my.custom.spring.PersistentTokenBasedRememberMeServicesCustom"/>