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,您可以轻松快捷地完成这项任务。 –

相关问题