1

在我的應用程序中,在註冊用戶時,我將這些字段保存在MONGO DB中,當用戶嘗試使用正確的憑據登錄時,我將用戶名,密碼和jwt生成的令牌然後我將發送響應與存儲令牌。然後在客戶端(在我的控制器)我使用本地存儲來存儲令牌,以便我可以發送相同的令牌客戶端發送的每個請求。但我發現一些有關此過程的問題:在nodejs/ExpressJs和Angular(單頁應用程序)中的基於令牌的授權

  1. 我爲每個用戶生成一個相同的令牌。因此,如果任何第三方能夠獲取該令牌,則他可以訪問受限制的頁面。
  2. 我是通過在MONGODB中存儲生成的令牌來浪費db中的空間
  3. 任何人都可以訪問保存在localstorage中的令牌,而不是用戶。
  4. 對於我的單頁應用程序中的每個請求,我再次查詢mongodb以獲取該用戶的令牌並進行驗證。在此,我正在檢查客戶端和服務器端。

我用的智威湯遜在我的應用程序

生成令牌,節點,快速,貓鼬難道我下好procedure.If沒有,你可以請提供我的做法或任何新的辦法解決。 我搜索了很多網站的基於令牌的授權和基於會話的授權,但沒有爲我工作。 注意:我是Nodejs,AngularjS的初學者

回答

0

當用戶註冊時,您需要像現在一樣生成JWT。沒關係。但是,您不需要將其保存到數據庫。您沒有問,但我認爲密碼不應以明文形式存儲。在將其保存到數據庫之前,您可以使用bcrypt進行加密。

當用戶嘗試用正確的憑據登錄,然後我會送存儲令牌

是的,這是正確的方式做了迴應。

然後在客戶端(在我的控制器中)我使用localstorage來存儲令牌,以便我可以爲客戶端發送的每個請求發送相同的令牌。

是,在客戶端,您可以將JWT保存到本地存儲,並在隨後請求到服務器發送。

現在你要點:

  1. 所以,你不會有相同的JWT各一次,您可以在有效載荷的「EXP」要求(我假設你正在使用的東西像jwt-simple來生成JWT)。喜歡的東西:

    var payload = { sub: account.username, exp: moment().add(10, 'days').unix() }; var token = jwt.encode(payload, "secret");

  2. 你並不需要在JWTs存儲在數據庫中。在某些情況下,令牌發行者(授權服務器)與資源服務器不同。資源服務器僅在請求中接收JWT,但資源服務器無法觸及授權服務器使用的數據庫。附註:如果您最終需要支持刷新令牌,即交給客戶端的JWT最終需要過期,則可以將刷新令牌存儲在數據庫中。刷新令牌與JWT(訪問令牌)不同。支持刷新令牌的複雜性會增加。

  3. 本地存儲是不是你存儲密碼,但它可以被用來存儲JWTs。出於這個原因,JWT必須並且應該在一段時間後過期。

  4. 不知道你說你檢查這兩個客戶端和服務器端的意思。當客戶端需要訪問資源時(再次假設資源服務器可能與授權服務器不一樣),資源服務器傳遞的唯一信息就是JWT。任何人都可以解碼智威湯遜。例如,嘗試將您的JWT粘貼到此網站http://jwt.io/。這就是爲什麼JWT不應包含任何敏感數據。但是如果資源服務器知道授權服務器在對JWT進行編碼時使用的祕密,那麼資源服務器可以驗證簽名。回到第三個項目符號,這就是將JWT存儲在客戶端本地存儲中的原因。

更新我更新這回答大家的一些問題在留言框中。

用戶點擊「登錄」按鈕觸發角控制器張貼到服務器的請求時,是這樣的:

$http.post(url, { 
    username: $scope.username, 
    password: $scope.password 
}).success(function(res) { ... }) 

服務器接收POST請求時,它檢查用戶名/密碼,那麼它會產生一個JWT ,併發回給瀏覽器。請注意,它不必將JWT保存到數據庫。該代碼會是這樣的

var payload = { 
    sub: account.username, 
    exp: moment().add(10, 'days').unix() 
}; 
var token = jwt.encode(payload, "secret"); 
res.status(200).json({  
    token: token 
}); 

回到在客戶端,在上面的成功()回調,現在你可以保存JWT在本地存儲:現在

.success(function(res) { $window.localStorage.setItem('accessJWT', res.token) }) 

的用戶進行身份驗證。現在,當用戶想要訪問受保護的資源時,用戶不必提供用戶名/密碼。通過可從本地存儲中檢索的JWT,客戶端現在可以使用承載方案將JWT放入請求的Authorization標頭中,並將請求發送到服務器。在代碼中,它會:

headers.Authorization = 'Bearer ' + token; 

服務器接收到請求。同樣,接收此請求的服務器不必與生成上述JWT的服務器相同。這兩臺服務器可以位於兩個不同的大陸。即使上面保存了JWT,對於無法訪問存儲JWT的數據庫的服務器也無濟於事。但是這個服務器可以從請求頭中取出不記名令牌,驗證令牌並繼續正常的任務。

希望這會有所幫助。

+0

沒有在數據庫中存儲令牌,我如何在每次用戶登錄時在服務器端操作我的令牌。 我想我可以將令牌存儲在$ rootscope中,而不是本地存儲中?如果我沒有錯! 或我應該去參加會議嗎? 而且我怎麼能每次不同地爲特定用戶生成令牌? –

+0

不,會話是JWT從未需要的,它旨在在移動設備中工作。正如我所說的,要獲得不同的標記,請添加基於時間的到期聲明。每次生成令牌時,時間都會有所不同,因此聲明將有所不同,因此有效負載將有所不同,因此令牌會有所不同。同樣,你不需要存儲令牌。用戶登錄時,檢查有效憑證。如果有效,請發出令牌。當用戶想要訪問某個資源時,會在請求頭中傳遞一個令牌,然後資源服務器可以驗證該令牌。 –

+0

一切都很好,但我怎麼能得到在serverside(在server.js)每個請求生成的令牌,becoz我不存儲令牌,我在我的MongoDB中使用jwt生成的令牌? –

0

您不希望將JWT存儲在貓鼬中,因爲它在登錄時出現在標頭中。首先生成一個令牌,然後使用像crypto這樣的模塊對其進行哈希處理。

有不同的方法來做到這一點,他們都使用Passport處理令牌。下面是一個示例項目Satellizer

我建議您生成angular-fullstack項目。然後瀏覽server/auth文件夾和客戶端/帳戶文件夾。您將看到如何安全地處理基於MEAN的應用程序中的身份驗證。

0

您應該將令牌存儲在高級鍵值緩存工具中,例如:Redis 這會顯着提高性能。

您將第一次從數據庫獲得令牌,然後它應該存儲在Redis中。我曾經將token設置爲key和username作爲值。下一個請求,令牌將從緩存中提供。使用Redis,您可以設置令牌過期。

+0

在數據庫中存儲令牌是好事還是壞事? 我可以在數據庫中存儲令牌嗎? ie 當用戶使用正確的憑證登錄時,我將生成一個帶有JWT.Sign(帶有一些密鑰)的令牌並將其存儲在某些服務器端訪問的地方(不知道我可以在哪裏存儲?可以請你簡單介紹一下),我將發送帶有生成的令牌的響應,以便在客戶端(在我的控制器中)我可以將令牌存儲在$ rootScope中(如果沒有錯誤,存儲在本地存儲中並不是好事)。對於每一個請求,我都會檢查兩邊的令牌! 我在做正確的方式! –

+0

我可以通過Redis頁面閒置15秒來設置令牌的到期時間嗎?這樣,當用戶處於閒置狀態15秒鐘時,我將重置客戶端和服務器端的令牌,這將再次顯示登錄頁面。 @Maher Abuthraa –

+0

以下是restify + mongoose + redis的工作版本:https://github.com/rgallagher27/node-restify-oauth2-mongodb+oAuth2.0,try,瞭解如何在該項目中使用Redis。真正需要了解的是oAuth2.0的工作方式。對於我來說,使用數據庫是很好的,如果到期是長期的,如果你不需要用戶經常插入憑證......許多移動應用程序使用這種方式。或者就像你的情況一樣,只有因爲空閒時間只有15秒,你纔可以將令牌保存在緩存中。通過Redist,您可以輕鬆快捷地完成這項任務。 –

相關問題