Nest.js路由鉴权和登陆 注册(学习笔记)


前言

Nest.js的鉴权验证,登陆和注册


以下是本篇文章正文内容,下面案例可供参考

一、创建一个基本的 CURD结构

描述:创建完成后,会得到一个这样的目录:里面专门写我们的登陆注册功能

命令 nest g res auth

在这里插入图片描述

二、进行实体类auth.entity.ts 和 create-auth.dto.ts 的 编写

1.auth.entity.ts

代码如下(示例):

import { Column,PrimaryGeneratedColumn,Entity } from "typeorm";

@Entity()
export class Auth {
    @PrimaryGeneratedColumn()
    id:number

    @Column()
    username:string

    @Column()
    password:string

}

2.create-auth.dto.ts

export class CreateAuthDto {
    username: string;
    password:string;
}

三、编写Controller和Service

代码如下(示例):

3.1 Controller层

import { Controller, Post, Body } from '@nestjs/common';
import { AuthService } from './auth.service';
import { CreateAuthDto } from './dto/create-auth.dto';
import { Public } from 'src/common/public.decorator';

@Controller('auth')
export class AuthController {
  constructor(private readonly authService: AuthService) { }

  // 注册
  // @Public()
  @Post("/signup")
  signup(@Body() signupData: CreateAuthDto) {
    return this.authService.signup(signupData)
  }

  // 登录
  // @Public()
  @Post("/login")
  login(@Body() loginData: CreateAuthDto) {
    return this.authService.login(loginData)
    
  }
}

3.2 Service层

import { BadRequestException, Injectable } from '@nestjs/common';
import { CreateAuthDto } from './dto/create-auth.dto';
import { Auth } from './entities/auth.entity';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import * as bcryptjs from 'bcryptjs';
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class AuthService {
  constructor(
    @InjectRepository(Auth) private readonly user: Repository<Auth>,
    private readonly JwtService: JwtService
  ) {}
  // 注册
  async signup(signupData: CreateAuthDto) {
    const findUser = await this.user.findOne({
      where: { username: signupData.username }
    });
    if (findUser && findUser.username === signupData.username)
      return '用户已存在';
    // 对密码进行加密处理
    signupData.password = bcryptjs.hashSync(signupData.password, 10);
    await this.user.save(signupData);
    return {
      data: {
        msg:'注册成功'
      }
    };
  }

  // 登录
  async login(loginData: CreateAuthDto) {
    const findUser = await this.user.findOne({
      where: { username: loginData.username }
    });
    // 没有找到
    if (!findUser) return new BadRequestException('用户不存在');

    // 找到了对比密码
    const compareRes: boolean = bcryptjs.compareSync(
      loginData.password,
      findUser.password
    );
    // 密码不正确
    if (!compareRes) return new BadRequestException('密码不正确');
    const payload = { username: findUser.username};
    console.log(payload,'token');
    
    // 返回token信息  携带Bearer 
    return {
      token: 'Bearer ' + this.JwtService.sign(payload),
      msg: '登录成功'
    };
  }
}

四、Module模块的引入

  1. 确保在auth.module.ts中进行了注册
import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Auth } from './entities/auth.entity';
import { JwtModule, JwtService } from '@nestjs/jwt';
import { jwtConstants } from './constants';
import { JwtAuthStrategy } from './jwt-auth.strategy';

@Module({
  imports: [TypeOrmModule.forFeature([Auth])],
  controllers: [AuthController],
  providers: [AuthService]
})
export class AuthModule {}

  1. 确保在app.module.ts中也进行了注册
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AuthModule } from './auth/auth.module';
@Module({
  imports: [AuthModule],
  controllers: [AppController],
  providers: [AppService],  
})
export class AppModule {}

五、 进行JWT的注册工作生成token

在auth.module.ts进行注册

import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Auth } from './entities/auth.entity';
import { JwtModule, JwtService } from '@nestjs/jwt';
import { jwtConstants } from "./constants"
import { JwtAuthStrategy } from "./jwt-auth.strategy"


@Module({
  imports: [TypeOrmModule.forFeature([Auth]),
  JwtModule.register({
    secret: jwtConstants.secret,
    // 这个参数就是jwtConstants中的文件数据  设置jwt有效时间的
    signOptions: { expiresIn: jwtConstants.expiresIn }
  })
  // 进行注册jwt模块
  ],
  controllers: [AuthController],
  providers: [AuthService]
})
export class AuthModule { }

在这里插入图片描述

六、postman工具测试

注意:先注册一个账号,在进行登录

在这里插入图片描述


我们可以发现登录后生成了token  注意:我这里对后台返回响应二次封装了,所以你们的返回数据格式可能有所不同。

在这里插入图片描述


七、路由的鉴权

这里我们有了token后,我们就可以实现对接口的保护了,凡是没有登陆的用户就不能随意访问我们的后台真实数据接口。

7.1 创建导航守卫

jwt-auth.guard.ts 文件代码如下(示例):



import {
  CanActivate,
  ExecutionContext,
  Injectable,
  UnauthorizedException
} from '@nestjs/common';
import { jwtConstants } from '../constants';
import { JwtService } from '@nestjs/jwt';
import { Reflector } from '@nestjs/core';
import { IS_PUBLIC_KEY } from 'src/common/public.decorator';
import { Request } from 'express';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(
    private jwtService: JwtService,
    private reflector: Reflector
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
      context.getHandler(),
      context.getClass()
    ]);
    if (isPublic) {
      // 💡 See this condition
      return true;
    }

    const request = context.switchToHttp().getRequest();
    const token = this.extractTokenFromHeader(request);
    if (!token) {
      throw new UnauthorizedException();
    }
    try {
      const payload = await this.jwtService.verifyAsync(token, {
        secret: jwtConstants.secret
      });
      // 💡 We're assigning the payload to the request object here
      // so that we can access it in our route handlers
      request['user'] = payload;
    } catch {
      throw new UnauthorizedException();
    }
    return true;
  }

  // 给request直到类型
  private extractTokenFromHeader(request: Request): string | undefined {
    const [type, token] = request.headers.authorization?.split(' ') ?? [];
    return type === 'Bearer' ? token : undefined;
  }
}

7.2 创建自定装饰器@Public()

用来验证是否需要被鉴权,加上这个装饰器就代表不需要鉴权,通常我们的登陆和注册是不需要鉴权的

public.decorator.ts 文件

import { SetMetadata } from "@nestjs/common";
export const IS_PUBLIC_KEY = 'isPublic'
export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);

7.3 创建管理JWT文件

管理JWT的有效时间和密钥

constants.ts 文件
export const jwtConstants = {
  secret: "leeKey", // 密钥
  expiresIn: "7d" // token有效时间  
}

7.4 全局启用身份验证

在app.module.ts文件中进行全局的注册提供

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AuthModule } from './auth/auth.module';
import { JwtService } from '@nestjs/jwt';
import { APP_GUARD } from '@nestjs/core';
import { AuthGuard } from './auth/jwt-auth/jwt-auth.guard';
@Module({
  imports: [AuthModule],
  controllers: [AppController],
  providers: [AppService,JwtService,
    // // 注册全局守卫
    {
      provide: APP_GUARD,
      useClass: AuthGuard,
    }
  ],
})
export class AppModule {}

注意点

1.首先链接数据库操作本章没有写,需自行连接(如:typeorm,prisma数据库)
2.我们自定义的装饰器@Public() 需要在不需要鉴权的Controller层中进行引用装饰
在这里插入图片描述

总结

以上就是今天要讲的内容,本文仅仅简单介绍了Nest.js的鉴权使用,而Nest.js提供了大量能使我们快速便捷地处理数据的函数和方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值