2015-10-06 109 views
2

好吧,所以我只是進入MEAN堆棧,並且正在嘗試使用Passport.js構建應用程序。如何使用passport.js正確實現serializeUser?

我剛剛開始用戶序列化來維護會話。在他們爲榜樣,Passport使用該序列化和反序列化:

passport.serializeUser(function(user, done) { 
    done(null, user.id); 
}); 

passport.deserializeUser(function(id, done) { 
    User.findById(id, function(err, user) { 
    done(err, user); 
    }); 
}); 

所以,我的問題是:被認爲是安全的這個例子嗎?如果我理解這個權利,這是不是意味着客戶端可以僞造用戶標識以登錄爲具有該標識的用戶?

我猜我問的是,是他們的例子認爲是「安全」和做事的正確方法,或者是預期你會改變這些功能來生成唯一的序列化。如果這被認爲是安全的,那麼我想我缺少這是如何工作的東西,我很樂意在需要填補。

在另一方面,如果這是不是安全的,我希望我寫的自己的功能代替這些,下面是這樣做的有效和安全的方式:

  • 在用戶序列化後,生成一個隨機哈希,並把它放在用戶的數據庫條目。隨機哈希是表示該用戶的序列號。
  • 反序列化後,查找數據庫中的隨機散列並返回相應的用戶。如果沒有發現哈希引發某種錯誤。
  • 當用戶註銷時,從其數據庫中的條目中刪除其串行散列。

如果我的邏輯直到這裏是有效的,那麼生成這個隨機哈希的正確方法是什麼?

回答

2

是的,這就是你如何做序列化/反序列化。沒有從客戶端收到id

會話信息存儲到本地會話存儲區,例如。數據庫,在一個隨機ID下。例如,express-session使用uid-safe來生成會話ID。此ID設置爲一個cookie,然後發送給客戶端。

當客戶端發出請求時,如果cookie沒有被篡改(通常ID是使用您在初始化會話時定義的secret進行簽名),則會從cookie中讀取會話ID。使用此ID,會從本地會話存儲中讀取實際會話數據。這是用於反序列化的id來自哪裏。

下面是一個例子存儲到MongoDB的會話對象可能是什麼樣子:

{ 
    "_id" : "_RXnIfFeb_qH6AXMO2ounrxlJZPHkwda", 
    "session" : "{\"cookie\":{\"originalMaxAge\":null,\"expires\":null,\"secure\":false,\"httpOnly\":true,\"path\":\"/\"},\"passport\":{\"user\":\"5614c62e4372842244660dcf\"}}" 
} 

這裏的_id是什麼簽名,並在cookie被髮送。該session字符串,解碼JSON對象是:

{ 
    "cookie": { 
    "originalMaxAge": null, 
    "expires": null, 
    "secure": false, 
    "httpOnly": true, 
    "path": "/" 
    }, 
    "passport": { 
    "user": "5614c62e4372842244660dcf" 
    } 
} 

這裏,passport.user是我的應用程序seralizeUser正在加載會話時給予deserializeUser返回的實際用戶ID。

那麼如果更改cookie內容會發生什麼?如果cookie被簽名,它將被無效,因爲修改後的值與簽名不匹配。如果未簽名,則在查詢會話存儲時使用該值。查詢不會返回任何內容,因爲您更改了ID並且數據庫中沒有匹配的會話(除非您已經發現/猜測了另一活動會話的會話ID - 即執行session hijacking)。

+0

好吧,最終passport.user可以是我想要的任何東西,因爲它不會被髮送到客戶端,對吧? – danielhep

+0

理論上是的,但沒有嘗試過,如果返回例如。對象或數組工作。 – vesse