在 MEAN 堆栈中添加令牌以验证请求

2025年3月17日 | 阅读 7 分钟

上一节中,我们成功实现了并使用了我们的 **check-Auth** 中间件来保护某些路由免受未经授权的访问。现在,我们希望在前端使用该令牌并在登录时实际存储它,然后将其附加到我们发送到后端的请求中。我们将使用以下步骤添加令牌以验证请求

1) 首先,我们将进入我们的 auth.service.ts 文件,在那里我们进行登录。我们将定义一个新属性,它的类型是字符串。最初,此属性将是未定义的,但在我们获取响应的 login() 方法中,我们知道此响应将包含令牌。因此,我们应该能够从响应中提取令牌。应该有一个令牌属性,我们可以像这样配置此 POST 请求以使其了解它


Adding the Token to Authenticate the Requests in MEAN Stack

2) 我们想在应用程序的其他部分使用该令牌。我们希望在某些请求的帖子服务中使用它。为此,我们将在 auth 服务文件中添加一个新方法,因为令牌字段是私有的。我们可以将其变为公共的,但我们只是在此处添加一个新方法,即 **getToken()**,并在其中返回此令牌。


Adding the Token to Authenticate the Requests in MEAN Stack

3) 现在,我们将返回到我们的 **service.ts** 文件并获取该令牌以使用它。现在要使用它,我们需要将 auth 服务注入到帖子服务中,然后将一个标头添加到我们所有的传出 HTTP 请求中。我们将使用一种不同的方式来完成此操作,我们将为我们的 HTTP 客户端创建一个所谓的拦截器,这是 angular http 客户端提供的一个功能。我们可以添加一个拦截器,这些拦截器是在任何传出 HTTP 请求上运行的函数,然后我们可以操作这些传出请求,例如附加我们的令牌,这正是我们想要做的。

因此,我们将在身份验证文件夹中创建一个新文件,并将其命名为 auth-interceptor.ts,以表明其中包含一个拦截器。

Adding the Token to Authenticate the Requests in MEAN Stack

4) 现在,这是 angular http 客户端提供的官方功能,我们通过创建一个普通类并将其命名为 **AuthInterceptor** 来创建这样的拦截器。此类必须实现 angular 提供的一个接口,即 **HttpInterceptor**,并且我们像这样定义 **intercept()** 方法


Adding the Token to Authenticate the Requests in MEAN Stack

5) 此 intercept() 方法接受两个参数。第一个参数是我们正在拦截的请求,因为我们提到它适用于传出请求,并且它的类型是 HttpRequest,这是一种可以包装各种信息和数据的静态类型。


Adding the Token to Authenticate the Requests in MEAN Stack

6) 第二个参数是我们在 NodeJS 端的中间件中可能知道的东西。我们也有下一个参数,这个拦截器的工作方式很像中间件,只是用于传出而不是传入请求。因此,我们没有响应对象,因为我们无法配置响应。我们只参与发送请求。

但我们确实获得了该请求,并且我们获得了 next,它允许我们离开该拦截器并允许我们应用程序的其他部分,例如我们订阅响应的部分。我们允许这些部分获取该请求及其响应。因此,这就是为什么我们需要 next 来允许拦截器或该拦截器中的请求继续其在应用程序中的旅程,并且该 next 参数的类型是 HttpHandler。


Adding the Token to Authenticate the Requests in MEAN Stack

7) 此方法必须返回一些东西,并且此方法将返回对 next.handle() 的调用。此 handle 方法由 next 提供,在此处我们允许请求继续其旅程。因此,我们只需在 handle 方法中传递请求,这将是一个不做任何事情的有效拦截器。这只会获取请求并允许它继续而不会被更改。


Adding the Token to Authenticate the Requests in MEAN Stack

8) 现在,我们将更改它,我们将创建一个新的常量来保存我们的令牌,为此,我们需要将我们的 auth-service 注入到此拦截器中,因为我们可以从那里获取令牌。接收注入服务的服务必须具有 @Injectable 注解才能将服务注入到其他服务中。我们无论如何都将其添加到我们所有其他服务中,因为我们提供它们的方式。我们将以不同的方式提供拦截器,因为 angular http 客户端要求我们以不同的方式提供它。

但是我们仍然需要添加一个空的 injectable 注解,这样我们就可以真正将服务注入到此服务中,这是 angular 的一个要求。


Adding the Token to Authenticate the Requests in MEAN Stack

9) 现在,我们将在该拦截器类中使用 authservice。我们将通过简单地调用 authservice 类的 getToken() 方法来创建新令牌,如下所示


Adding the Token to Authenticate the Requests in MEAN Stack

10) 现在,我们操作请求以保存此令牌,并且在我们操作它之前应该克隆它。我们必须这样做,因为如果我们直接编辑该传出请求,由于请求在内部工作和处理的方式,我们将导致不必要的副作用和问题。因此,我们将创建一个新的常量,在那里我们将调用请求的 clone() 方法,它将创建该请求的副本。我们可以将克隆的配置传递给克隆,不仅克隆请求,还可以编辑克隆。我们想要编辑它,实际上,我们想要精确地编辑它的标头。

标头应该是我们原始请求的标头,但我们还想查看一个额外的标头,我们可以使用 set 来完成。


Adding the Token to Authenticate the Requests in MEAN Stack

11) Set 听起来会覆盖所有旧标头,但它不会。它只会添加一个新标头,并为其设置值,但如果该标头已经存在,它将覆盖它。因此,在 clone 函数中,我们将设置 Authorization 标头,其值将是我们的 authToken。


Adding the Token to Authenticate the Requests in MEAN Stack

这将创建一个包含此 Authorization 标头和我们令牌的请求,现在它是我们想要转发的 authRequest,它现在应该离开我们的应用程序。

12) 现在我们正在获取或操作传入请求,并且我们在 Authorization 标头上添加了我们的令牌。更准确地说,这不起作用。请记住我们提到的关于 Bearer 单词的事情。我们的值实际上应该是 Bearer,然后是空格,然后是 authToken,如下所示


Adding the Token to Authenticate the Requests in MEAN Stack

这是我们在后端提取数据的方式,我们可以省略它,这只是我们经常看到的一种约定。

13) 所以,现在我们已经添加了它,但我们的中间件被忽略了。我们不需要将其添加到我们的 Angular 应用程序中。要添加它,我们必须将其注入为服务或提供为服务,但不是使用 provided root,而是略有不同。我们将进入我们的 **module.ts** 文件,并在其中向提供者数组添加一个新对象或 JavaScript 对象。此对象必须具有几个属性。

a. 第一个属性是 provide 属性,在那里我们提供一个令牌,即 **HTTP_INTERCEPTOR**。此令牌是从 @angular/common/http 导入的。

b. 因为现在我们正在告诉 Angular,对于 Angular 将寻找的此标识符,Angular http 客户端将寻找它,对于此令牌,我们想要提供一个新值。然后使用 useClass 属性提供该值,在这里,我们必须指向我们的拦截器,即 **Auth-interceptor**。

c. 现在,我们可以在一个应用程序中拥有多个拦截器,因此我们将第三个值,即 **multi**,并将其值设置为 true。

这只是告诉 Angular 不要覆盖现有拦截器,而是将其添加为附加拦截器,并且 Angular http 客户端将处理内部。

Adding the Token to Authenticate the Requests in MEAN Stack

现在,我们的拦截器已注册,每个传出请求都将收到该令牌。这也意味着不需要该令牌的请求也将收到它,但它将是 undefined 并且应该不是问题。

我们将返回我们的应用程序并尝试在登录后插入一个新帖子。

注意:我们将收到“Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response”错误。我们将收到此错误,因为我们不允许此标头。因此,我们将在后端的 app.js 文件中允许此标头并设置 Authorization 标头,如下所示


Adding the Token to Authenticate the Requests in MEAN Stack

现在,如果我们转到我们的 Angular 应用程序,我们没有收到该错误。

Adding the Token to Authenticate the Requests in MEAN Stack
Adding the Token to Authenticate the Requests in MEAN Stack
Adding the Token to Authenticate the Requests in MEAN Stack

现在,一切都运行良好,但我们的标头看起来很糟糕。我们将在下一节中改进 UI 标头以反映身份验证状态。