- 创建项目
- Nest 控制器
- nest 配置路由请求数据
- Nest 服务
- Nest 模块
- 配置静态资源
- 配置模板引擎
- Cookie 的使用
- Session 的使用
- 跨域,前缀路径、网站安全、请求限速
- 管道、守卫、拦截器、过滤器、中间件
- 一例看懂中间件、守卫、管道、异常过滤器、拦截器
- 数据验证
- 配置抽离
- 环境配置
- 文件上传与下载
- 实现图片随机验证码
- 邮件服务
- nest 基于 possport + jwt 做登陆验证
- 对数据库的密码加密:md5 和 bcryptjs
- 角色权限
- 定时任务
- 接入 Swagger 接口文档
- nest 连接 Mongodb
- typeORM 操作 Mysql 数据库
- nest 统一处理数据库操作的查询结果
- 数据库实体设计与操作
- typeorm 增删改查操作
- typeorm 使用事务的 3 种方式
- typeorm 一对一关系设计与增删改查
- typeorm 一对多和多对一关系设计与增删改查
- typeorm 多对多关系设计与增删改查
- nest 连接 Redis
- 集成 redis 实现单点登录
- Q:nestJS 注入其他依赖时为什么还需要导入其 module
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
nest 基于 possport + jwt 做登陆验证
方式与逻辑
- 基于 possport 的本地策略和 jwt 策略
- 本地策略主要是验证账号和密码是否存在,如果存在就登陆,返回token
- jwt 策略则是验证用户登陆时附带的 token是否匹配和有效,如果不匹配和无效则返回401 状态码
yarn add @nestjs/jwt @nestjs/passport passport-jwt passport-local passport yarn add -D @types/passport @types/passport-jwt @types/passport-local
jwt 策略 jwt.strategy.ts
// src/modules/auth/jwt.strategy.ts import { Strategy, ExtractJwt, StrategyOptions } from 'passport-jwt'; import { Injectable } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { jwtConstants } from './constants'; @Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { constructor() { super({ jwtFromRequest: ExtractJwt.fromHeader('token'), ignoreExpiration: false, secretOrKey: jwtConstants.secret, // 使用密钥解析 } as StrategyOptions); } //token 验证, payload 是 super 中已经解析好的 token 信息 async validate(payload: any) { return { userId: payload.userId, username: payload.username }; } }
本地策略 local.strategy.ts
// src/modules/auth/local.strategy.ts import { Strategy, IStrategyOptions } from 'passport-local'; import { Injectable, HttpException, HttpStatus } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { AuthService } from './auth.service'; //本地策略 //PassportStrategy 接受两个参数: //第一个:Strategy,你要用的策略,这里是 passport-local,本地策略 //第二个:别名,可选,默认是 passport-local 的 local,用于接口时传递的字符串 @Injectable() export class LocalStrategy extends PassportStrategy(Strategy) { constructor(private authService: AuthService) { super({ usernameField: 'username', passwordField: 'password', } as IStrategyOptions); } // validate 是 LocalStrategy 的内置方法 async validate(username: string, password: string): Promise<any> { //查询数据库,验证账号密码,并最终返回用户 return await this.authService.validateUser({ username, password }); } }
constants.ts
// src/modules/auth/constants.ts export const jwtConstants = { secret: 'secretKey', };
使用守卫 auth.controller.ts
// src/modules/auth/auth.controller.ts import { Controller, Get, Post, Request, UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; import { AuthService } from './auth.service'; @Controller('auth') export class AuthController { constructor(private readonly authService: AuthService) {} // 登录测试 无需 token @UseGuards(AuthGuard('local')) //本地策略,传递 local,执行 local 里面的 validate 方法 @Post('login') async login(@Request() req) { //通过 req 可以获取到 validate 方法返回的 user,传递给 login,登陆 return this.authService.login(req.user); } // 在需要的地方使用守卫,需要带 token 才可访问 @UseGuards(AuthGuard('jwt'))//jwt 策略,身份鉴权 @Get('userInfo') getUserInfo(@Request() req) {//通过 req 获取到被验证后的 user,也可以使用装饰器 return req.user; } }
在 module 引入 jwt 配置和数据库查询的实体 auth.module.ts
// src/modules/auth/auth.module.ts import { LocalStrategy } from './local.strategy'; import { jwtConstants } from './constants'; import { Module } from '@nestjs/common'; import { PassportModule } from '@nestjs/passport'; import { JwtModule } from '@nestjs/jwt'; import { AuthService } from './auth.service'; import { AuthController } from './auth.controller'; import { JwtStrategy } from './jwt.strategy'; import { UsersEntity } from '../user/entities/user.entity'; import { TypeOrmModule } from '@nestjs/typeorm'; @Module({ imports: [ TypeOrmModule.forFeature([UsersEntity]), PassportModule, JwtModule.register({ secret: jwtConstants.secret, signOptions: { expiresIn: '10d' }, }), ], controllers: [AuthController], providers: [AuthService, LocalStrategy, JwtStrategy], exports: [AuthService], }) export class AuthModule {}
auth.service.ts
// src/modules/auth/auth.service.ts import { Injectable } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import { compareSync } from 'bcryptjs'; @Injectable() export class AuthService { constructor( @InjectRepository(UsersEntity), private readonly usersRepository: Repository<UsersEntity>, private jwtService: JwtService ) {} validateUser(username: string, password: string) { const user = await this.usersRepository.findOne({ where: { username }, select: ['username', 'password'], }); if (!user) ToolsService.fail('用户名或密码不正确'); //使用 bcryptjs 验证密码 if (!compareSync(password, user.password)) { ToolsService.fail('用户名或密码不正确'); } return user; } login(user: any) { const payload = { username: user.username }; // 把信息存在 token return { token: this.jwtService.sign(payload), }; } }
最后在 app.module.ts 中导入即可测试
// app.modules.ts import { AuthModule } from './modules/auth/auth.module'; @Module({ imports: [ ... AuthModule, // 导入模块 ], controllers: [AppController], providers: [], }) export class AppModule implements NestModule {}
使用 postman 测试
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论