文章目录
前言
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模块的引入
- 确保在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 {}
- 确保在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提供了大量能使我们快速便捷地处理数据的函数和方法。