2013-02-06 65 views
2

在我的應用中,我有一個User模型,它有一個rememberable_token列。創建用戶時,隨機安全字符串保存在before_create過濾器作爲用戶安全令牌:關於會話cookie的Ruby on Rails安全性

user.rememberable_token = SecureRandom.urlsafe_base64 

在會話控制器,它創建與該令牌,這樣的價值永久性的Cookie關閉瀏覽器時,用戶不會被註銷,只被註銷,當他們通過logout行動註銷:

會話控制器

def create 
    . 
    . 
    cookies.permanent.signed[:permanent_user_session] = user.rememberable_token 
end 

def logout 
    cookies.delete :permanent_user_session 
    redirect_to root_url 
end 

共okie在應用程序控制器中用於確定是否存在當前用戶以及在幾個控制器中用於確定用戶是否已登錄和授權的before_filter。

應用控制器

def current_user 
    @current_user ||= User.find_by_rememberable_token(cookies.signed[:permanent_user_session]) if cookies.signed[:permanent_user_session] 
end 

def authorize 
    unless User.find_by_rememberable_token(cookies.signed[:permanent_user_session]) 
    render :action => 'login' 
    end 
end 

的問題是,如果這是安全的,或者很容易出現會話劫持?如果它很容易被劫持,那麼在session#logout方法中,它是否可以在刪除現有cookie(但不創建具有該值的新cookie)之前爲用戶創建一個新的rememberable_token?

謝謝。

回答

1

如果有人偷餅乾,此代碼:

def current_user 
@current_user ||= User.find_by_rememberable_token(cookies.signed[:permanent_user_session]) if cookies.signed[:permanent_user_session] 
end 

仍然有效。在您的註銷方法中,您必須從用戶表中刪除令牌並在登錄時重新創建。

基本上,您在創建時應該在每次登錄時完成並在每次註銷時恢復。

+0

如果用戶保持登錄狀態一週,那麼竊取cookie的任何人都可以竊取他們的會話。這是令人擔憂還是實際上可能與任何類型的登錄會話cookie? – ilmhlueq

+0

這不是會話cookie的漏洞。即使您將會話保留在服務器端,並且cookie上只有會話ID,也是如此。您可以每30分鐘過期一次會話,但每次請求都會重置計時器。這使得攻擊者只需30分鐘的時間間隔即可執行攻擊,但也會使用戶無法登錄數週。 – Eduard

+3

另外,請注意:請勿將持久性登錄COOKIE(代幣)存儲在您的數據庫中,僅此一項!登錄令牌是密碼等效的,所以如果攻擊者抓住你的數據庫,他/她可以使用令牌登錄到任何帳戶,就像它們是明文登錄密碼組合一樣。因此,在存儲持久登錄標記時使用強烈的哈希散列(bcrypt/phpass)。這和更多關於登錄,你可以找到這個主題:http://stackoverflow.com/questions/549/the-definitive-guide-to-forms-based-website-authentication – Eduard

0

我可能做到這一點:

會話創建:

random_string = SecureRandom.urlsafe_base64 
cookies.permanent.signed[:permanent_user_session] = random_string 
user.rememberable_token = Digest::MD5.hexdigest(random_string) && user.save 

會話破壞:

cookies.delete :permanent_user_session 

在應用控制器:

def current_user 
    @current_user ||= User.find_by_rememberable_token(Digest::MD5.hexdigest(cookies.signed[:permanent_user_session])) if cookies.signed[:permanent_user_session] 
end 

def authorize 
    unless @current_user 
    render :action => 'login' 
    end 
end 

這方式,你是摧毀令牌的散列,併爲每次新登錄重新生成一個新的登錄(並在每次登出時過期)。 Rails負責CSRF,但長期會話可能不是一個好主意。