在 Express.js 中刷新 JWT

Posted

技术标签:

【中文标题】在 Express.js 中刷新 JWT【英文标题】:Refreshing JWT in Express.js 【发布时间】:2015-10-26 12:17:04 【问题描述】:

我在我的 Angular.js 应用程序中使用 JWT 进行身份验证,在服务器端使用 Express.js。

基本上,当用户登录时,会创建一个新令牌(使用https://github.com/auth0/node-jsonwebtoken)并将其发送回客户端。如果令牌在客户端也有效(angular.js 部分,使用https://github.com/auth0/angular-jwt),则会创建一个新用户并将令牌存储在 cookie 中。

因此,对服务器上特定路径的每个请求都受到令牌验证的保护。但是,我的令牌有过期时间。现在让我们为了论证起见说过期时间是 30 秒;用户可以主动使用我的应用程序 30 秒,之后,他将被注销。这并不完全是用户友好的。

所以我所做的是,对于服务器的每个请求,我都会创建一个新令牌并将其发送回响应的头部。当我在 Angular.js 客户端收到响应时,我会读取令牌并覆盖 cookie 中的令牌。这样,只要客户端处于活动状态(或者更确切地说,向服务器端发出请求),令牌就会被刷新。

现在我想知道以下内容:

    这种方法正确吗?不利的一面是,该令牌会在每个请求中创建并在每个响应头中发回。 Cookie 经常被覆盖(性能问题?) 正确的方法是什么? 如果没有对服务器的请求,令牌过期是否正常?客户端可能仍在使用应用程序,但是,如果他只是在客户端写入(或读取)内容,则令牌不会被刷新。

感谢您的宝贵时间和回复!

【问题讨论】:

【参考方案1】:

    是的,这是一种有效的方法。这是许多人采取的相同方法, 包括流行的 Angular 模块 ng-token-auth。你可能 考虑将令牌保存到本地存储,并回退到 如果浏览器不支持 cookie 存储(请参阅 http://caniuse.com/#feat=namevalue-storage 报道)。

    我会按照你的描述去做。

    一种解决方案是使用$interval 基本上ping API。您需要做的就是发送一个令牌以获取一个新的令牌(即,在像您现在这样的标题中)。跟踪您发送了多少“ping”。您可以在某些操作上重置“ping”的数量,例如在 ui-router 的$stateChangeSuccess(即导航到新视图)或您喜欢的任何操作上,包括提交表单或其他非 ping 请求。当“ping”的数量达到您的阈值时,警告用户他们的会话即将到期,并在延迟后擦除存储的令牌并将其注销。检查您的 ping 响应是否存在来自 API 的身份验证错误,表明用户可能需要注销和/或重定向。

也许您只是给出了 30 秒作为示例令牌寿命。我建议您更接近您想要的浏览会话超时。作为参考,请考虑 Ruby gem devise_token_auth 默认为 2 周,.NET defaults 默认为 10 小时。您的需求可能会有所不同。

【讨论】:

【参考方案2】:

使用刷新令牌也解决了这个问题。您的访问令牌的寿命很短,并通过签名进行验证。刷新令牌的寿命更长,用于获取新的访问令牌。

当刷新令牌用于获取新的访问令牌时,是进行额外检查的好时机:刷新令牌是否已被撤销?此用户帐户是否仍然有效?

这两个令牌都可以存储在安全 cookie 中,并在每次请求时提供。这样做可以让您的服务器在需要时透明地使用刷新令牌,并在 cookie 响应中设置新的访问令牌。

这是我们为Express-Stormpath 采用的方法,并记录在文档的Authentication 部分。如果您想卸载您的身份验证层,我建议您使用Stormpath。 (免责声明:我在那里工作,并编写了那个模块)。

【讨论】:

以上是关于在 Express.js 中刷新 JWT的主要内容,如果未能解决你的问题,请参考以下文章

如何在不重新启动我的 Express.js 项目的情况下刷新 API 端点

如何查询 Express.js 中的特定内容?

使用 react-router v4 和 express.js 进行服务器渲染

ExpressJS 更改路由而不刷新

在 Express.js 中,我是不是应该返回响应?

如何在 Node.js / Express.js 中将中间件放在它自己的文件中