在 MEAN Stack 中将令牌保存在本地存储中

17 Mar 2025 | 6 分钟阅读

在我们之前的章节中,我们成功地在应用程序中添加了令牌计时器。一小时后,令牌将过期,我们的帐户将被注销,并且我们必须再次登录。剩下的部分是将令牌保存在本地存储中,因为如果我们不注销就重新加载页面,则必须再次登录。为了将该令牌存储到本地存储中,我们将使用以下步骤

1) 我们将返回到我们的 auth.service.ts 文件并创建一个新的私有方法,即 saveAuthData。我们将其设为私有,因为我们仅从该服务内部调用它。


Saving the Token in the Local Storage in MEAN Stack

2) 在此方法中,我们希望获取要保存的数据,即令牌和 expirationDate。此 expirationDate 应该是日期,而不是以秒为单位的时间,因为以秒为单位的时间是相对的度量,在将来对我们没有帮助。在那里,我们需要清楚地了解令牌何时过期。


Saving the Token in the Local Storage in MEAN Stack

3) 现在,所有这些数据都将被序列化并存储在本地存储中。访问本地存储非常容易。我们可以访问本地存储 API,然后我们只需调用 setItem() 将值存储在那里。该值将以键值对的形式设置。

我们还希望设置 expirationDate。


Saving the Token in the Local Storage in MEAN Stack

我们将日期转换为 ISOString,这是日期的序列化和标准样式版本,然后我们可以使用它在以后读取数据后重新创建它。

4) 我们还需要添加另一个方法,clearAuthData。在此方法中,我们将调用 removeItem() 方法来删除令牌和过期时间 - 此 clearAuthData() 方法在 logout() 方法中被调用以清除本地存储。


Saving the Token in the Local Storage in MEAN Stack

5) 现在,我们需要调用 saveAuthData, 并且此方法将在 login() 方法中被调用。为了调用此方法,我们必须通过创建一个新常量来创建日期,然后将信息传递给该函数。


Saving the Token in the Local Storage in MEAN Stack

6) 现在,我们将使用该信息在应用程序启动时初始化我们的身份验证状态,为此,我们将添加另一个方法,即 authAuthUser(),在这里我们尝试在本地存储中获取了信息的情况下自动验证用户。为此,我们还需要另一个方法 getAuthData() 方法。在此方法中,我们将通过像这样调用 getItem() 方法从本地存储中获取令牌和 expirationDate


Saving the Token in the Local Storage in MEAN Stack

7) 现在,我们将检查令牌和 expirationDate,如果它不存在,则我们不返回任何内容。否则,我们将返回一个 JavaScript 对象,其中包含我们的令牌和 expirationDate。


Saving the Token in the Local Storage in MEAN Stack

8) getAuthData() 方法将在 authAuthUser() 中被调用。我们将调用此方法并将数据存储到一个新的常量中,即 authInformation。如果我们没有获得身份验证信息,我们将不返回任何内容。现在,我们将检查令牌是否仍然有效,为此,我们获取了 expirationDate。我们无法验证它是否是有效的令牌,只有服务器才能做到,但至少我们可以从过期角度判断它是否仍然有效。因此,我们将检查过期日期是否仍在将来。我们将通过创建一个新的日期对象来获取当前日期时间,然后我们可以简单地检查它是否在将来,方法是创建一个新的常量,即 isInFuture, 我们通过比较 expirationDate 与当前日期和时间来创建一个布尔值。如果 expirationdate 大于当前日期和时间,则我们有一个将来的日期。


Saving the Token in the Local Storage in MEAN Stack

9) 现在,我们将检查 isInFuture 是 true 还是 false。如果为 true,则表示用户已通过身份验证,我们将 this.token 设置为本地存储中的令牌。我们还将 isAuthenticated 设置为 true 并推送该信息,因此我们将设置 authStatusListener,调用 next 并将 true 传递给每个人,因为用户现在已通过身份验证。


Saving the Token in the Local Storage in MEAN Stack

10) 现在,我们还需要设置计时器。因此,由于需要在两个地方完成此操作,我们可能会在 login() 方法中重构 tokenTimer 代码并将其放入一个新地方。因此,我们将把它从 subscribe 方法中拉出来,并创建一个新方法,即 setAuthTimer()。在此方法中,我们获取持续时间并将 tokenTimer 代码粘贴在这里。


Saving the Token in the Local Storage in MEAN Stack

11) expiresInDuration 现在是持续时间。现在,在 login() 方法的 subscribe 方法中,我们将调用此 setAuthTimer() 方法并将 expiresInDuration 传递给该方法。


Saving the Token in the Local Storage in MEAN Stack

12) 我们还需要在 autoAuthUser() 中调用 setAuthTimer() 方法

此代码行将生成一个错误,因为我们还没有 expiresInDuration。因此,与其检查日期是否在将来,不如检索差异。我们将把名称 isInFuture 替换为 expiresInDuration。然后,此 expiresInDuration 应为 expirationDate-now。这将引发错误,因此我们将 getTime() 方法附加到 expirationDate 和当前时间。


Saving the Token in the Local Storage in MEAN Stack

13) 现在,我们知道我们正在从将来某个时间戳中检测当前时间戳。如果当前时间大于 exipresIn,这也将是一个导航数字。因此,我们将检查 expiresInDuration 是否大于零,因为如果是,我们知道该日期在将来。如果它小于或等于零,则表示就在现在或过去,因此过期时间将在过去,这意味着它已过期。


Saving the Token in the Local Storage in MEAN Stack

14) 我们以毫秒为单位获取 exipresInDuration,但我们的 authTimer 以秒为单位工作。我们将通过将其除以 1000 来做到这一点。


Saving the Token in the Local Storage in MEAN Stack

15) 现在,一切都很好,剩下的事情是运行该方法,并且运行它的好地方是在 app 组件中。在那里,我们知道此组件会在我们的应用程序启动时首先加载。因此,我们将在 OnInit 中实现,并且在 OnInit() 方法中,我们希望使用来自我们的身份验证服务的某些内容。因此,我们也需要在这里注入我们的身份验证服务。


Saving the Token in the Local Storage in MEAN Stack

16) 现在,在 ngOnInit() 方法中,我们将从服务调用 autoAuthUser() 方法,以启动该自动身份验证工作流程。


Saving the Token in the Local Storage in MEAN Stack

现在,我们保存所有文件并返回到我们的 angular 应用程序。我们登录,登录后,我们重新加载页面。

Saving the Token in the Local Storage in MEAN Stack
Saving the Token in the Local Storage in MEAN Stack

重新加载后

Saving the Token in the Local Storage in MEAN Stack

17) 它工作正常,但问题是我们的标题以某种方式没有反映此更新的信息。重新加载后,我们仍然看到登录和注册按钮。因此,标题没有获得有关用户已通过身份验证的信息。因此,为了解决此问题,我们将返回到 header.component.ts 文件,并且除了设置此侦听器外,我们还应该出于与之前在帖子列表组件中相同的理由,将 userIsAuthenticated 设置为 this.authService.getIsAuth()。


Saving the Token in the Local Storage in MEAN Stack

现在,我们将保存该文件,并且我们的应用程序将重新加载。我们将获取标题,其中包含注销和新建帖子按钮。

Saving the Token in the Local Storage in MEAN Stack

现在,一切都工作正常,并且缺少一件事,那就是,我们没有将我们的用户连接到我们的帖子。我们稍后将在新部分中执行此操作。

下载完整项目(Authentication.zip)