auth.module.ts
import { Module } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { JwtModule, JwtService } from '@nestjs/jwt';
import { MongooseModule } from '@nestjs/mongoose';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { User, UserSchema } from '../user/entities/user.entity';
@Module({
imports: [
JwtModule.registerAsync({
inject: [ConfigService],
useFactory: (config: ConfigService) => {
return {
global: true,
secret: config.get<string>('JWT_SECRET'),
signOptions: {
expiresIn: config.get<string | number>('JWT_EXPIRES'),
},
};
},
}),
MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]),
],
controllers: [AuthController],
providers: [AuthService, JwtService],
exports: [MongooseModule, AuthService, JwtService],
})
export class AuthModule {}
验证服务.ts
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { User } from '../user/entities/user.entity';
import { JwtService } from '@nestjs/jwt';
import { LoginDto } from './dto/login.dto';
@Injectable()
export class AuthService {
constructor(
@InjectModel(User.name)
private userModel: Model<User>,
private jwtService: JwtService,
) {}
async login(loginDto: LoginDto): Promise<{ token: string }> {
const { username, password } = loginDto;
const user = await this.userModel.findOne({ username });
if (!user) {
throw new UnauthorizedException('Invalid email or password');
}
if (user.password !== password) {
throw new UnauthorizedException('Invalid email or password');
}
const token = await this.jwtService.signAsync({ id: user._id });
return { token };
}
}
auth.guard.ts
import {
CanActivate,
ExecutionContext,
Injectable,
UnauthorizedException,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import { InjectModel } from '@nestjs/mongoose';
import { Request } from 'express';
import { Model } from 'mongoose';
import { User } from '../user/entities/user.entity';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(
@InjectModel(User.name)
private userModel: Model<User>,
private jwtService: JwtService,
private readonly configService: ConfigService,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const token = this.extractTokenFromHeader(request);
if (!token) {
throw new UnauthorizedException(
'You are not authorized to access this resource.',
);
}
try {
const payload = await this.jwtService.verifyAsync(token, {
secret: this.configService.get<string>('JWT_SECRET'),
});
console.log('payload ->>', payload);
const user = await this.userModel.findById(payload.id);
if (!user) {
throw new UnauthorizedException('User not found.');
}
request['user'] = user;
} catch {
throw new UnauthorizedException(
'You are not authorized to access this resource.',
);
}
return true;
}
private extractTokenFromHeader(request: Request): string | undefined {
const [type, token] = request.headers.authorization?.split(' ') ?? [];
return type === 'Bearer' ? token : undefined;
}
}
当我调用登录API时,
错误:secretOrPrivateKey必须具有值
我在stackoverflow上找到了一些答案。它说从auth.module.ts
中的提供程序中删除JwtService
。
我也试过这个,但它给予我另一个错误
Nest无法解析AuthGuard(UserModel,?、ConfigService)。请确保索引[1]处的JwtService参数在BookModule上下文中可用。
我不知道我错过了什么
Thanks in advance
快乐编码!
1条答案
按热度按时间toiithl61#
可能是你没有定义你的env变量或者ConfigModule设置错误。根据the official NestJs documentation,您必须在AppModule导入中包含
ConfigModule.forRoot()
。为了处理各种env文件(例如.development.env
),必须像这样指定它们的路径:同样,最后但并非最不重要的是,检查你的环境文件中的拼写错误。它应该包含
JWT_SECRET
的值。虽然这与最初的问题无关,但考虑使用像zod
这样的库来验证您的.env文件,以避免拼写错误或繁琐的env调试。