在 NestJS 服务器应用程序中使用 Clerk 进行身份验证
介绍
本文提供了使用 Clerk 在 NestJS 后端应用程序中实现身份验证和授权的全面分步指南。
什么是文员?
Clerk 是一个综合平台,提供可嵌入的用户界面、灵活的 API 以及用于无缝用户身份验证和管理的直观且强大的仪表板。它涵盖了从会话管理和多因素身份验证到社交登录、魔术链接、电子邮件或短信一次性密码等的一切。
为什么要使用文员?
身份验证和安全要求、趋势和最佳实践总是在不断发展,因为数据保护和隐私变得越来越重要。通过将这些责任转移给专业服务提供商,您可以专注于构建应用程序的核心功能并更快地交付。
像 Clerk 这样的平台可以为您承担这些安全任务。
先决条件
- Typescript 基础知识
- 熟悉 NestJS 基础知识
- 了解后端身份验证概念
- 运行 Node 18 或最新版本
项目设置
该项目需要一个新的或现有的 NestJS 项目、一个 Clerk 帐户和应用程序,以及 Passport、Passport Strategy 和 Clerk 后端 SDK 等库。
创建 NestJS 项目
您可以使用 Nest CLI 轻松设置新的 NestJS 项目。使用您喜欢的任何包管理器,运行以下命令来创建新的 Nest 应用程序:
$ pnpm add -g @nestjs/cli $ nest new clerk-auth
查看 NestJS 文档以了解更多详细信息。
设置您的文员帐户和应用程序
如果您还没有 Clerk 帐户,请创建一个 Clerk 帐户并在 Clerk 仪表板中设置一个新应用程序。您可以在 Clerk 网站上开始使用。
安装所需的库
可以使用以下命令安装该项目所需的库:
$ pnpm add @clerk/backend @nestjs/config @nestjs/passport passport passport-custom
环境配置
在项目的根目录中创建一个 .env 文件来管理不同环境、生产、开发或登台的变量。
添加以下变量,用从 Clerk 帐户仪表板获取的实际密钥替换占位符。
# .env CLERK_PUBLISHABLE_KEY=YOUR_PUBLISHABLE_KEY CLERK_SECRET_KEY=YOUR_SECRET_KEY
要使用 ConfigService 访问整个应用程序中的环境变量,请将 ConfigModule 导入根 AppModule。
// src/app.module.ts import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, }), ], }) export class AppModule {}
在 NestJS 中集成 Clerk
本节介绍如何在您的 NestJS 项目中集成和使用 Clerk 后端 SDK。
创建 Clerk 客户端提供商
将 Clerk 客户端注册为提供程序,使其可以使用装饰器注入到类中,从而可以在整个代码库中的任何需要的地方使用它,如接下来的部分所示。
$ pnpm add -g @nestjs/cli $ nest new clerk-auth
在 AppModule 中注册 ClerkClientProvider
接下来,您需要向 Nest 注册提供程序以启用依赖项注入。
$ pnpm add @clerk/backend @nestjs/config @nestjs/passport passport passport-custom
使用带有职员签发的 JWT 的护照
当用户通过 Clerk 的托管页面或前端应用程序注册或登录时,Clerk 会发出 JWT 令牌。然后,此令牌作为不记名令牌发送到向 NestJS 后端应用程序发出的请求的授权标头中。
制定文员策略
在NestJS中,Passport是推荐的实现身份验证策略的方式。您将创建一个自定义 Clerk 策略,用于使用 Clerk 客户端验证令牌。
# .env CLERK_PUBLISHABLE_KEY=YOUR_PUBLISHABLE_KEY CLERK_SECRET_KEY=YOUR_SECRET_KEY
validate() 方法返回 NestJS 自动附加到 request.user 的用户数据。
创建身份验证模块
创建一个 AuthModule,它提供 Clerk 策略并与 PassportModule 集成。然后,在AppModule中注册AuthModule。
// src/app.module.ts import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, }), ], }) export class AppModule {}
// src/providers/clerk-client.provider.ts import { createClerkClient } from '@clerk/backend'; import { ConfigService } from '@nestjs/config'; export const ClerkClientProvider = { provide: 'ClerkClient', useFactory: (configService: ConfigService) => { return createClerkClient({ publishableKey: configService.get('CLERK_PUBLISHABLE_KEY'), secretKey: configService.get('CLERK_SECRET_KEY'), }); }, inject: [ConfigService], };
实施路由保护
受保护的路由是需要用户经过身份验证才能访问的路由。
创建文员身份验证守卫
守卫根据某些运行时条件确定特定请求是否应由路由处理程序处理。
如果您想默认保护应用程序中的所有路由,则需要执行以下步骤:
- 创建一个公共装饰器来标记无需身份验证即可访问的路由。
- 实现 ClerkAuthGuard 来限制对受保护路由的访问,仅允许经过身份验证的用户继续。
// src/app.module.ts import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { ClerkClientProvider } from 'src/providers/clerk-client.provider'; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, }), ], providers: [ClerkClientProvider], }) export class AppModule {}
// src/auth/clerk.strategy.ts import { User, verifyToken } from '@clerk/backend'; import { Injectable, Injectable, UnauthorizedException } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { PassportStrategy } from '@nestjs/passport'; import { Strategy } from 'passport-custom'; import { UsersService } from 'src/users/users.service'; import { Request } from 'express'; import { ClerkClient } from '@clerk/backend'; @Injectable() export class ClerkStrategy extends PassportStrategy(Strategy, 'clerk') { constructor( @Inject('ClerkClient') private readonly clerkClient: ClerkClient, private readonly configService: ConfigService, ) { super(); } async validate(req: Request): Promise<User> { const token = req.headers.authorization?.split(' ').pop(); if (!token) { throw new UnauthorizedException('No token provided'); } try { const tokenPayload = await verifyToken(token, { secretKey: this.configService.get('CLERK_SECRET_KEY'), }); const user = await this.clerkClient.users.getUser(tokenPayload.sub); return user; } catch (error) { console.error(error); throw new UnauthorizedException('Invalid token'); } } }
全局启用身份验证
由于默认情况下您的大多数端点都会受到保护,因此您可以将身份验证防护配置为全局防护。
// src/auth/auth.module.ts import { Module } from '@nestjs/common'; import { ClerkStrategy } from './clerk.strategy'; import { PassportModule } from '@nestjs/passport'; import { ClerkClientProvider } from 'src/providers/clerk-client.provider'; import { ConfigModule } from '@nestjs/config'; @Module({ imports: [PassportModule, ConfigModule], providers: [ClerkStrategy, ClerkClientProvider], exports: [PassportModule], }) export class AuthModule {}
定义受保护的公共路线
在这两个控制器中,AppController 中使用 Public 装饰器来将路由指定为公共。相比之下,AuthController 中不需要装饰器来将路由指定为受保护,因为身份验证防护默认情况下全局应用。
// src/app.module.ts import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { ClerkClientProvider } from 'src/providers/clerk-client.provider'; import { AuthModule } from 'src/auth/auth.module'; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, }), AuthModule, ], providers: [ClerkClientProvider], }) export class AppModule {}
// src/decorators/public.decorator.ts import { SetMetadata } from '@nestjs/common'; export const IS_PUBLIC_KEY = 'isPublic'; export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);
注意:记得在AppModule中注册AppController,在AuthModule中注册AuthController。
结论
Clerk 作为一个平台,负责处理身份验证和安全责任,紧跟最新趋势和最佳实践。这使您能够专注于构建应用程序的核心功能并加速您的开发过程。
在本指南中,我们介绍了实施 Clerk 身份验证的步骤,从设置项目到保护路由。这些基本步骤应该可以帮助您开始探索身份验证服务平台的可能性。
本文末尾包含该项目的完整功能示例。
达米王
/
职员巢授权
在 NestJS 后端应用程序中使用 Clerk 身份验证和用户管理
Clerk-NestJS 身份验证
在 NestJS 后端应用程序中使用 Clerk 身份验证和用户管理
里面有什么?
这个 monorepo 包含以下软件包和应用程序:
应用程序和软件包
- api:一个 NestJS 应用
每个包和应用程序都是 100% TypeScript。
实用工具
这个 monorepo 已经为您设置了一些附加工具:
- 用于静态类型检查的 TypeScript
- 用于代码检查的 ESLint
- 代码格式更漂亮
以上是在 NestJS 服务器应用程序中使用 Clerk 进行身份验证的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

JavaScript在Web开发中的主要用途包括客户端交互、表单验证和异步通信。1)通过DOM操作实现动态内容更新和用户交互;2)在用户提交数据前进行客户端验证,提高用户体验;3)通过AJAX技术实现与服务器的无刷新通信。

JavaScript在现实世界中的应用包括前端和后端开发。1)通过构建TODO列表应用展示前端应用,涉及DOM操作和事件处理。2)通过Node.js和Express构建RESTfulAPI展示后端应用。

理解JavaScript引擎内部工作原理对开发者重要,因为它能帮助编写更高效的代码并理解性能瓶颈和优化策略。1)引擎的工作流程包括解析、编译和执行三个阶段;2)执行过程中,引擎会进行动态优化,如内联缓存和隐藏类;3)最佳实践包括避免全局变量、优化循环、使用const和let,以及避免过度使用闭包。

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。 1)C 用于解析JavaScript源码并生成抽象语法树。 2)C 负责生成和执行字节码。 3)C 实现JIT编译器,在运行时优化和编译热点代码,显着提高JavaScript的执行效率。

Python更适合数据科学和自动化,JavaScript更适合前端和全栈开发。1.Python在数据科学和机器学习中表现出色,使用NumPy、Pandas等库进行数据处理和建模。2.Python在自动化和脚本编写方面简洁高效。3.JavaScript在前端开发中不可或缺,用于构建动态网页和单页面应用。4.JavaScript通过Node.js在后端开发中发挥作用,支持全栈开发。
