在现代Web应用程序开发中,身份验证是确保用户安全访问受保护资源的关键环节。特别是在Node.js生态系统中,Passport作为一个功能强大且广泛使用的身份验证中间件库,为开发者提供了灵活且可扩展的身份验证解决方案。本文将深入探讨如何在NestJS框架中集成Passport,通过实现账户密码策略和JWT策略,来优化身份验证流程,提升应用程序的安全性和用户体验。
文章导航
一、Passport的基础知识和基本功能
首先,让我们从Passport的基础开始:
Passport
本身可以看作一框架
Passport
是最流行的node.js
身份验证库
使用策略模式(设计模式),决定当前是获取 token
还是解析 token
。
使用 @nestjs/passport
模块,可以很容易地将这个库与 Nest
应用程序集成。
Passport
提供了一种名为 Passport-local
的策略,它实现了一种用户名/密码身份验证机制。
Passport-jwt
就是实现JWT解析身份验证机制。
二、怎么在Passport中生成jwt策略
Passport提供了多种身份验证策略,其中Passport-local实现了用户名/密码身份验证机制,而Passport-jwt则实现了JWT解析身份验证机制。为了生成JWT,我们需要使用@nestjs/jwt模块提供的JwtService,该服务提供了sign()方法用于生成JWT。在NestJS中,我们通常会创建一个AuthService服务来封装与身份验证相关的逻辑,包括登录验证、用户验证等。
需要用到的模块:
@nestjs/jwt
,提供了JwtService
,可以直接用sign()
方法返回名。
import { checkPassword } from '@libs/common/utils/password';
import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { User } from '@prisma/client';
import { PayloadDto } from 'apps/admin/src/auth/dto/payload.dto';
import { UsersService } from 'apps/admin/src/users/users.service';
@Injectable()
export class AuthService {
constructor(
private usersService: UsersService,
private jwtService: JwtService,
) {}
login(user: User) {
const payload: PayloadDto = { id: user.id };
return { token: this.jwtService.sign(payload) }; // 返回json web token
}
async validateUser(email: string, password: string): Promise<User> {
const user = await this.usersService.getUserByEmail(email);
if (!checkPassword(user.password, password)) {
return null;
}
return {
...user,
password: undefined, // 密碼不做返回
};
}
}
直接注入依赖就完事了
三、怎么配置Passport的本地策略
接下来,我们将通过扩展PassportStrategy类来配置Passport的本地策略(即账户密码策略)。
使用
@nestjs/passport
,您可以通过扩展PassportStrategy
类来配置passport
策略。
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { User } from '@prisma/client';
import { AuthService } from 'apps/admin/src/auth/auth.service';
import { Strategy } from 'passport-local';
@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
constructor(private authService: AuthService) {
super({ usernameField: 'email', passwordField: 'password' });
}
validate(email: string, password: string): Promise<User> {
return this.authService.validateUser(email, password);
}
}
第一个参数对应用户名字段(usernameFiled
)的值,第二个参数对应密码字段(passwordFiled
)的值。
通过调用子类中的 super()
方法传递策略选项,可以选择传递一个选项
对象。
对于每个策略,Passport
将使用适当的特定于策略的一组参数调用验证
函数(使用@nestjs/Passport
中的valitor()
方法实现。
passport-local
是Passport提供的一种本地身份验证策略,它使用用户名和密码来验证用户。
代码中,重新配置了用户名、密码字段名字。
这意味着在验证用户凭据时,
本地
策略将期望从传递给验证
方法的参数中读取'email'
和'密码'
字段的值。
这里的字段,对应著DTO
字段。
import { ApiProperty } from '@nestjs/swagger';
import { IsString } from 'class-validator';
export class LoginDto {
@ApiProperty({
description: '用戶郵箱',
default: 'Taoister39@outlook.com',
required: true,
})
@IsString()
readonly email: string;
@ApiProperty({
description: '用戶密碼',
default: '123456',
required: true,
})
@IsString()
readonly password: string;
}
四、怎么实现JWT策略模式
除了本地策略外,我们还需要实现JWT策略来支持基于token的身份验证。
passport-jwt
包是实现JWT
策略的Passport
包,@type/passport-jwt
提供TypeScript
类型定义。
import { PassportStrategy } from '@nestjs/passport';
import { PayloadDto } from 'apps/admin/src/auth/dto/payload.dto';
import { ExtractJwt, Strategy } from 'passport-jwt';
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() {
// console.log(process.env.JWT_SECRET, ' jwt secret ');
super({
secretOrKey: process.env.JWT_SECRET,
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), // 從請求頭中提取token
ignoreExpiration: false, // 過期自動返回401錯誤
});
}
// jwt裏只攜帶了id
async validate(payload: PayloadDto) {
return payload;
}
}
对于JWT
策略,Passport
首先验证JWT
的签名并解码JSON
.然后调用我们的valdit()
方法,该方法将解码后的JSON
作为其单个参数传递。
五、JwtModule和PassportModule的集成与应用
最后,我们需要将上述策略、JwtModule和PassportModule集成到NestJS应用程序中。这通常涉及到在AuthModule中导入这些模块和提供者,并配置JwtModule的相关选项(如密钥和签名选项)。通过AuthGuard守卫,我们可以决定在特定的路由或控制器中使用哪种身份验证策略。
import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { LocalStrategy } from 'apps/admin/src/auth/strategy/local.strategy';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { JwtStrategy } from 'apps/admin/src/auth/strategy/jwt.strategy';
import { UsersModule } from 'apps/admin/src/users/users.module';
@Module({
controllers: [AuthController],
providers: [AuthService, LocalStrategy, JwtStrategy],
imports: [
JwtModule.register({
secret: process.env.JWT_SECRET,
signOptions: {
expiresIn: '1d', // token 有效爲 1天
},
}),
UsersModule,
PassportModule,
],
})
export class AuthModule {}
首先提供刚刚的策略,然后导入JwtModule
、PassportModule
,对应的JwtService
就可以注入依赖,以及通过封装的策略,在应用中加载。通过AuthGuard
守卫决定使用哪个策略。
结语
通过在NestJS中集成Passport并实现账户密码策略和JWT策略,我们可以构建一个既安全又高效的身份验证系统。这不仅提升了应用程序的安全性,还优化了用户体验。随着技术的不断发展和用户需求的不断变化,我们将继续探索和优化身份验证的最佳实践,以确保我们的应用程序始终能够为用户提供安全、便捷的访问体验。
延展阅读:
大促期间客服容易漏回消息?电商商家怎么用智能工具高效提升客服响应速度?
智能客服回复不准确影响客户满意度?电商商家怎么通过数据分析快速提高其应答水平
顾客没耐心等人工,电商商家怎么通过智能客服自助服务提升询单转化率
咨询方案 获取更多方案详情