nest之passport登录

puxiaoshuai 2024-6-28 134 6/28

 

前言: 不同的认证方式虽然逻辑不同,但做的事情很类似

  • 用户名密码登录就是从 request 的 body 里取出 username、password 来认证。
  • jwt 是从 request 的 Authorization 的 header 取出 token 来认证。

依赖安装

npm install --save @nestjs/passport passport
实现用户名密码的认证,需要使用passport-local 的策略
npm install --save passport-local 
npm install --save-dev @types/passport-local

1.创建 local.strategy.ts

import { UserService } from './user.service';
import { PassportStrategy } from '@nestjs/passport';
import { InjectRepository } from '@nestjs/typeorm';
import { StrategyOptions, Strategy, ExtractJwt } from 'passport-jwt';
import { User } from './entities/user.entity';
import { Repository } from 'typeorm';
import { UnauthorizedException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
export class JwtStorage extends PassportStrategy(Strategy, 'jwt') {
  constructor(
    @InjectRepository(User)
    private readonly userRepository: Repository<User>, //需要注入,不能少
    private readonly userService: UserService,
    private readonly configService: ConfigService,
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: configService.get('JWT_SECRET'),
    } as StrategyOptions);
  }
  async validate(user: User) {
    //好像根本不要进行existUser这个判断, jwt只是根据传递的token信息在内部就进行了判断,并返回了user ,想了下还是需要,万一用户被删除了,你找不到,但是token这时候还是表示删除的用户,这个时候就有问题
    const existUser = await this.userService.getUser(user);
    if (!existUser) {
      throw new UnauthorizedException('当前用户不存在');
    }
    return existUser;
    //return user
  }
}

2.jwt.strategy.ts中

import { UserService } from './user.service';
import { PassportStrategy } from '@nestjs/passport';
import { InjectRepository } from '@nestjs/typeorm';
import { StrategyOptions, Strategy, ExtractJwt } from 'passport-jwt';
import { User } from './entities/user.entity';
import { Repository } from 'typeorm';
import { UnauthorizedException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
export class JwtStorage extends PassportStrategy(Strategy, 'jwt') {
  constructor(
    @InjectRepository(User)
    private readonly userRepository: Repository<User>, //需要注入,不能少
    private readonly userService: UserService,
    private readonly configService: ConfigService,
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: configService.get('JWT_SECRET'),
    } as StrategyOptions);
  }
  async validate(user: User) {
    //好像根本不要进行existUser这个判断, jwt只是根据传递的token信息在内部就进行了判断,并返回了user ,想了下还是需要,万一用户被删除了,你找不到,但是token这时候还是表示删除的用户,这个时候就有问题
    const existUser = await this.userService.getUser(user);
    if (!existUser) {
      throw new UnauthorizedException('当前用户不存在');
    }
    return existUser;
    //return user
  }
}

 

在 use.module中进行注册

import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { LocalStorage } from './local.strategy';
import { JwtStorage } from './jwt.strategy';
import { ConfigModule, ConfigService } from '@nestjs/config';

const jwtModule = JwtModule.registerAsync({
  imports: [ConfigModule],
  useFactory: async (configService: ConfigService) => ({
    secret: configService.get<string>('JWT_SECRET'),
    signOptions: { expiresIn: '12h' },
  }),
  inject: [ConfigService],
});
@Module({
  imports: [TypeOrmModule.forFeature([User]), PassportModule, jwtModule],
  controllers: [UserController],
  providers: [UserService, LocalStorage, JwtStorage, ConfigService],
  exports: [jwtModule],
})
export class UserModule {}

4.使用

@Controller('user')
export class UserController {
  constructor(
    private readonly userService: UserService,
    private readonly jwtService: JwtService,
  ) {}

  @Post('/register')
  register(@Body() createUserDto: CreateUserDto) {
    return this.userService.create(createUserDto);
  }
  createToken(user: Partial<User>) {
    return this.jwtService.sign(user);
  }
  @Post('login')
  @UseGuards(AuthGuard('local')) //这里使用local策略,返回token
  //login这里不用获取用户 username and password ,应该是直接在AuthGuard中间件中获取
  async login(@Req() req) {
    const user = req.user;
    const token = this.createToken({
      id: user.id,
      username: user.username,
    });
    //查询user,把user权限返回,[admin =99 ,visiter = 0]
    const existUser = await this.userService.getUser({ id: user.id });
    return {
      data: {
        token,
        user: {
          id: existUser.data.id,
          userName: existUser.data.username,
          role: existUser.data.role,
        },
      },
    };
  }

  @UseGuards(AuthGuard('jwt'))
  @Get()
  findAll(@Body() params) {
    return this.userService.findAll(params);
  }
  @UseGuards(AuthGuard('jwt'))
  @Get('/userInfo')
  findOne(@Body() params) {
    return this.userService.getUser(params);
  }
}

 

 

- THE END -

puxiaoshuai

6月28日17:16

最后修改:2024年6月28日
0

非特殊说明,本博所有文章均为博主原创。