nodejs/ExpressJs 和 Angular 中基于令牌的授权(单页应用程序)
Token based authorization in nodejs/ExpressJs and Angular(Single Page Application)
在我的应用程序中,在注册用户时,我在 MONGO DB.When 中使用这些字段保存用户名、密码和 jwt 生成的令牌 DB.When 用户尝试使用正确的凭据登录,然后我将发送响应在客户端(在我的控制器中)存储 token.Then 我正在使用本地存储来存储令牌,以便我可以为 client.But 发送的每个请求发送相同的令牌我发现了一些关于这个过程:
- 我每 time.So 为一个用户生成相同的令牌,如果任何第三方能够获得令牌,那么他就可以访问受限页面。
- 通过将生成的令牌存储在 MONGODB
中,我是否在数据库中浪费 space
- 除了用户之外,任何人都可以访问存储在 localstorage 中的令牌吗?
- 对于我的单页应用程序中的每个请求,我再次查询 mongodb 以获取该用户的令牌,并且 validating.Here,我正在检查客户端和服务器端。
我正在使用 jwt 在我的应用程序中生成令牌、Node、Express、Mongoose
我遵循的是好的 procedure.If 不是,你能为我的方法或任何新方法提供解决方案吗?
我在许多网站上搜索了基于令牌的授权和基于会话的授权,但对我没有任何帮助。
Note:I 是 Nodejs 初学者,AngularjS
您不想将 JWT 存储在 mongoose 中,因为它在登录时出现在 headers 中。您首先生成一个令牌,然后使用像 crypto 这样的模块对其进行哈希处理。
有不同的方法可以做到这一点,他们都使用 Passport which handles the tokens. Here's an example project Satellizer
我建议您生成 angular-fullstack 项目。然后浏览 server/auth 文件夹和 client/account 文件夹。您将了解如何在基于 MEAN 的应用程序中安全地处理身份验证。
您应该将令牌存储在高级键值缓存工具中,例如:Redis
这将显着提高性能。
您将第一次从数据库中获取令牌,然后将其存储在 Redis 中。我曾经将令牌设置为键,将用户名设置为值。下次请求时,令牌将从缓存中获取。使用 Redis,您可以为令牌设置过期时间。
当用户注册时,您需要像现在一样生成 JWT。没关系。但是,您不需要将其保存到数据库中。您没有问,但我认为密码不应以明文形式存储。您可以在将其保存到数据库之前使用 bcrypt 进行加密。
当用户尝试使用正确的凭据登录时,我将使用存储的令牌发送响应
是的,这是正确的做法。
然后在客户端(在我的控制器中)我使用本地存储来存储令牌,这样我就可以为客户端发送的每个请求发送相同的令牌。
是的,在客户端,您可以将 JWT 保存到本地存储,并在后续请求中将其发送到服务器。
现在你的要点:
这样您就不会每次都拥有相同的 JWT,您可以在有效负载中包含一个 "exp" 声明(我假设您使用的是 jwt-simple 生成 JWT)。类似于:
var payload = {
sub: account.username,
exp: moment().add(10, 'days').unix()
};
var token = jwt.encode(payload, "secret");
您不需要将 JWT 存储在数据库中。在某些情况下,令牌颁发者(授权服务器)与资源服务器不同。资源服务器仅接收请求中的 JWT,但资源服务器无法访问授权服务器使用的数据库。旁注:如果您最终需要支持刷新令牌,即您交给客户端的 JWT 最终需要过期,那么您可以将刷新令牌存储在数据库中。刷新令牌与 JWT(访问令牌)不同。支持刷新令牌的复杂性将会增加。
本地存储不是你存储密码的地方,但它可以用来存储 JWT。出于这个原因,JWT 必须并且应该在特定时间后过期。
不确定您所说的同时检查客户端和服务器端是什么意思。当客户端需要访问资源时(再次假设资源服务器可能与授权服务器不同是公平的),唯一传递给资源服务器的是 JWT。任何人都可以解码 JWT。例如,尝试将您的 JWT 粘贴到此站点 http://jwt.io/。这就是 JWT 不应包含任何敏感数据的原因。但是如果资源服务器知道授权服务器在对 JWT 进行编码时使用的秘密,则资源服务器可以验证签名。回到你的第三个项目符号,这就是为什么可以将 JWT 存储在客户端的本地存储中的原因。
更新我正在更新此内容以回答您在评论框中的一些问题。
用户点击 'Login' 按钮会触发 Angular 控制器向服务器 post 发出请求,例如:
$http.post(url, {
username: $scope.username,
password: $scope.password
}).success(function(res) { ... })
服务器收到POST请求,检查username/password,然后生成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
});
回到客户端,在上面的 success() 回调中,现在您可以将 JWT 保存在本地存储中:
.success(function(res) { $window.localStorage.setItem('accessJWT', res.token) })
用户现已通过身份验证。现在,当用户想要访问受保护的资源时,用户不必提供 username/password。有了可以从本地存储中检索到的 JWT,客户端现在可以使用承载方案将 JWT 放入请求的 Authorization header 中,然后将请求发送到服务器。在代码中,它会是:
headers.Authorization = 'Bearer ' + token;
服务器收到请求。同样,接收此请求的服务器不必与上面生成 JWT 的服务器相同。 2 个服务器可以位于 2 个不同的大陆。即使您保存了上面的 JWT,这对无法访问存储 JWT 的数据库的服务器也没有任何好处。但是此服务器可以从请求的 header 中提取不记名令牌,验证令牌并继续执行正常任务。
希望这对您有所帮助。
在我的应用程序中,在注册用户时,我在 MONGO DB.When 中使用这些字段保存用户名、密码和 jwt 生成的令牌 DB.When 用户尝试使用正确的凭据登录,然后我将发送响应在客户端(在我的控制器中)存储 token.Then 我正在使用本地存储来存储令牌,以便我可以为 client.But 发送的每个请求发送相同的令牌我发现了一些关于这个过程:
- 我每 time.So 为一个用户生成相同的令牌,如果任何第三方能够获得令牌,那么他就可以访问受限页面。
- 通过将生成的令牌存储在 MONGODB 中,我是否在数据库中浪费 space
- 除了用户之外,任何人都可以访问存储在 localstorage 中的令牌吗?
- 对于我的单页应用程序中的每个请求,我再次查询 mongodb 以获取该用户的令牌,并且 validating.Here,我正在检查客户端和服务器端。
我正在使用 jwt 在我的应用程序中生成令牌、Node、Express、Mongoose
我遵循的是好的 procedure.If 不是,你能为我的方法或任何新方法提供解决方案吗? 我在许多网站上搜索了基于令牌的授权和基于会话的授权,但对我没有任何帮助。 Note:I 是 Nodejs 初学者,AngularjS
您不想将 JWT 存储在 mongoose 中,因为它在登录时出现在 headers 中。您首先生成一个令牌,然后使用像 crypto 这样的模块对其进行哈希处理。
有不同的方法可以做到这一点,他们都使用 Passport which handles the tokens. Here's an example project Satellizer
我建议您生成 angular-fullstack 项目。然后浏览 server/auth 文件夹和 client/account 文件夹。您将了解如何在基于 MEAN 的应用程序中安全地处理身份验证。
您应该将令牌存储在高级键值缓存工具中,例如:Redis 这将显着提高性能。
您将第一次从数据库中获取令牌,然后将其存储在 Redis 中。我曾经将令牌设置为键,将用户名设置为值。下次请求时,令牌将从缓存中获取。使用 Redis,您可以为令牌设置过期时间。
当用户注册时,您需要像现在一样生成 JWT。没关系。但是,您不需要将其保存到数据库中。您没有问,但我认为密码不应以明文形式存储。您可以在将其保存到数据库之前使用 bcrypt 进行加密。
当用户尝试使用正确的凭据登录时,我将使用存储的令牌发送响应
是的,这是正确的做法。
然后在客户端(在我的控制器中)我使用本地存储来存储令牌,这样我就可以为客户端发送的每个请求发送相同的令牌。
是的,在客户端,您可以将 JWT 保存到本地存储,并在后续请求中将其发送到服务器。
现在你的要点:
这样您就不会每次都拥有相同的 JWT,您可以在有效负载中包含一个 "exp" 声明(我假设您使用的是 jwt-simple 生成 JWT)。类似于:
var payload = { sub: account.username, exp: moment().add(10, 'days').unix() }; var token = jwt.encode(payload, "secret");
您不需要将 JWT 存储在数据库中。在某些情况下,令牌颁发者(授权服务器)与资源服务器不同。资源服务器仅接收请求中的 JWT,但资源服务器无法访问授权服务器使用的数据库。旁注:如果您最终需要支持刷新令牌,即您交给客户端的 JWT 最终需要过期,那么您可以将刷新令牌存储在数据库中。刷新令牌与 JWT(访问令牌)不同。支持刷新令牌的复杂性将会增加。
本地存储不是你存储密码的地方,但它可以用来存储 JWT。出于这个原因,JWT 必须并且应该在特定时间后过期。
不确定您所说的同时检查客户端和服务器端是什么意思。当客户端需要访问资源时(再次假设资源服务器可能与授权服务器不同是公平的),唯一传递给资源服务器的是 JWT。任何人都可以解码 JWT。例如,尝试将您的 JWT 粘贴到此站点 http://jwt.io/。这就是 JWT 不应包含任何敏感数据的原因。但是如果资源服务器知道授权服务器在对 JWT 进行编码时使用的秘密,则资源服务器可以验证签名。回到你的第三个项目符号,这就是为什么可以将 JWT 存储在客户端的本地存储中的原因。
更新我正在更新此内容以回答您在评论框中的一些问题。
用户点击 'Login' 按钮会触发 Angular 控制器向服务器 post 发出请求,例如:
$http.post(url, {
username: $scope.username,
password: $scope.password
}).success(function(res) { ... })
服务器收到POST请求,检查username/password,然后生成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
});
回到客户端,在上面的 success() 回调中,现在您可以将 JWT 保存在本地存储中:
.success(function(res) { $window.localStorage.setItem('accessJWT', res.token) })
用户现已通过身份验证。现在,当用户想要访问受保护的资源时,用户不必提供 username/password。有了可以从本地存储中检索到的 JWT,客户端现在可以使用承载方案将 JWT 放入请求的 Authorization header 中,然后将请求发送到服务器。在代码中,它会是:
headers.Authorization = 'Bearer ' + token;
服务器收到请求。同样,接收此请求的服务器不必与上面生成 JWT 的服务器相同。 2 个服务器可以位于 2 个不同的大陆。即使您保存了上面的 JWT,这对无法访问存储 JWT 的数据库的服务器也没有任何好处。但是此服务器可以从请求的 header 中提取不记名令牌,验证令牌并继续执行正常任务。
希望这对您有所帮助。