上一主题 下一主题
ScriptCat,新一代的脚本管理器脚本站,与全世界分享你的用户脚本油猴脚本开发指南教程目录
返回列表 发新帖

nestjs passport及@nestjs/passport源码级分析(一)

[复制链接]
  • TA的每日心情
    慵懒
    2024-10-28 07:07
  • 签到天数: 193 天

    [LV.7]常住居民III

    712

    主题

    5966

    回帖

    6763

    积分

    管理员

    非物质文化遗产社会摇传承人

    积分
    6763

    荣誉开发者喜迎中秋油中2周年生态建设者

    发表于 2022-12-4 00:12:16 | 显示全部楼层 | 阅读模式

    前文

    今天看了nestjs的passport鉴权教程
    当时真的感觉...
    一言难尽,只教你创建目录,贴文件,但是不教到底为什么
    然后我决定看看官方的教程
    https://docs.nestjs.com/security/authentication
    发现...
    他妈的一个吊样啊喂
    那个人就是抄的官网啊喂
    所以到底有没有人讲讲
    经过很久的查阅资料...
    发现,没人研究过= =
    于是clone了一份源码自己慢慢读吧...
    所以就有了这篇文章!
    我们先大概理一下官方教程都做了什么
    https://docs.nestjs.com/security/authentication

    使用的库

    我们使用了nestjs框架,库尤passport,passport-local以及对应的类型库
    你可以输入下列命令安装
    npm install --save @nestjs/passport passport passport-local
    npm install --save-dev @types/passport-local

    官方教程中passport使用

    $ nest g module auth
    $ nest g service auth
    生成了一个auth模块和服务
    $ nest g module users
    $ nest g service users
    生成了一个user模块和服务
    user服务写了一个简单的查询demo

    import { Injectable } from '@nestjs/common';
    
    // This should be a real class/interface representing a user entity
    export type User = any;
    
    @Injectable()
    export class UsersService {
      private readonly users = [
        {
          userId: 1,
          username: 'john',
          password: 'changeme',
        },
        {
          userId: 2,
          username: 'maria',
          password: 'guess',
        },
      ];
    
      async findOne(username: string): Promise<User | undefined> {
        return this.users.find(user => user.username === username);
      }
    }

    然后在user模块导出

    import { Module } from '@nestjs/common';
    import { UsersService } from './users.service';
    
    @Module({
      providers: [UsersService],
      exports: [UsersService],
    })
    export class UsersModule {}

    在auth的服务里写一个基于user模块查询

    import { Injectable } from '@nestjs/common';
    import { UsersService } from '../users/users.service';
    
    @Injectable()
    export class AuthService {
      constructor(private usersService: UsersService) {}
    
      async validateUser(username: string, pass: string): Promise<any> {
        const user = await this.usersService.findOne(username);
        if (user && user.password === pass) {
          const { password, ...result } = user;
          return result;
        }
        return null;
      }
    }

    并且在auth模块导入user

    import { Module } from '@nestjs/common';
    import { AuthService } from './auth.service';
    import { UsersModule } from '../users/users.module';
    
    @Module({
      imports: [UsersModule],
      providers: [AuthService],
    })
    export class AuthModule {}

    然后在auth/local.strategy.ts
    写一个合法性校验的函数

    import { Strategy } from 'passport-local';
    import { PassportStrategy } from '@nestjs/passport';
    import { Injectable, UnauthorizedException } from '@nestjs/common';
    import { AuthService } from './auth.service';
    
    @Injectable()
    export class LocalStrategy extends PassportStrategy(Strategy) {
      constructor(private authService: AuthService) {
        super();
      }
    
      async validate(username: string, password: string): Promise<any> {
        const user = await this.authService.validateUser(username, password);
        if (!user) {
          throw new UnauthorizedException();
        }
        return user;
      }
    }

    并且在auth模块中导入

    import { Module } from '@nestjs/common';
    import { AuthService } from './auth.service';
    import { UsersModule } from '../users/users.module';
    import { PassportModule } from '@nestjs/passport';
    import { LocalStrategy } from './local.strategy';
    
    @Module({
      imports: [UsersModule, PassportModule],
      providers: [AuthService, LocalStrategy],
    })
    export class AuthModule {}
    

    使用方法,直接在对应录用中使用@UseGuards(AuthGuard('local'))

    import { Controller, Request, Post, UseGuards } from '@nestjs/common';
    import { AuthGuard } from '@nestjs/passport';
    
    @Controller()
    export class AppController {
      @UseGuards(AuthGuard('local'))
      @Post('auth/login')
      async login(@Request() req) {
        return req.user;
      }
    }

    测试

    使用curl,当然你也可以使用postman

    $ # POST to /auth/login
    $ curl -X POST http://localhost:3000/auth/login -d '{"username": "john", "password": "changeme"}' -H "Content-Type: application/json"
    $ # result -> {"userId":1,"username":"john"}

    那么我们就学习了最基本的使用
    可以自己动手操作一遍
    目前搞不懂很正常,后续会开始逐步分析到底怎么实现的

    结语

    撒花~

    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。

    发表回复

    本版积分规则

    快速回复 返回顶部 返回列表