我在服务器中实现 jwt 时遇到此错误。我正在使用 NestJs 并且正在遵循文档。我一直在这里寻找有关此错误的解决方案,但似乎没有任何作用。 我已将密钥存储在 .env 文件中,在 app.module 中添加 ConfigModule.forRoot() ,这样我就可以成功读取所有环境变量。这是我的代码,如果有人能指出我正确的方向。
app.module.ts
@Module({
imports: [
ConfigModule.forRoot(),
TypeOrmModule.forRoot({
type: 'postgres',
host: process.env.DB_HOST,
port: +process.env.DB_PORT,
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
entities: ['dist/**/*.entity{.ts,.js}'],
synchronize: false,
}),
UsersModule,
AuthModule,
PolsModule,
],
controllers: [UsersController, AuthController, PolsController],
providers: [UsersService, AuthService, PolsService, JwtService],
})
export class AppModule {}
auth.module.ts
@Module({
imports: [
UsersModule,
PassportModule,
JwtModule.register({
secret: process.env.JWT_SECRET_KEY,
signOptions: { expiresIn: '4h' },
}),
],
providers: [AuthService, UsersService, LocalStrategy, JwtStrategy],
controllers: [AuthController],
})
export class AuthModule {}
auth.controller.ts
@Controller('auth')
export class AuthController {
constructor(
private authService: AuthService,
private usersService: UsersService,
) {}
@UseGuards(LocalAuthGuard)
@Post()
async login(@Request() req) {
return this.authService.login(req.user);
}
}
auth.service.ts
@Injectable()
export class AuthService {
constructor(
private usersService: UsersService,
private jwtService: JwtService,
) {}
async login(user: any) {
const payload = { username: user.username, sub: user.id };
console.log(process.env.JWT_SECRET_KEY);
return {
access_token: this.jwtService.sign(payload),
};
}
}
控制台错误
// console.log(process.env.JWT_SECRET_KEY)
fb8C47vylwS
[Nest] 50225 - 01/07/2022, 17:46:37 ERROR [ExceptionsHandler] secretOrPrivateKey must have a value
Error: secretOrPrivateKey must have a value
at Object.module.exports [as sign] (/Users/user/dev/backend/pol-api/node_modules/jsonwebtoken/sign.js:107:20)
at JwtService.sign (/Users/user/dev/backend/pol-api/node_modules/@nestjs/jwt/dist/jwt.service.js:28:20)
at AuthService.login (/Users/user/dev/backend/pol-api/src/auth/auth.service.ts:26:37)
at AuthController.login (/Users/user/dev/backend/pol-api/src/auth/auth.controller.ts:29:29)
at /Users/user/dev/backend/pol-api/node_modules/@nestjs/core/router/router-execution-context.js:38:29
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at /Users/user/dev/backend/pol-api/node_modules/@nestjs/core/router/router-execution-context.js:46:28
at /Users/user/dev/backend/pol-api/node_modules/@nestjs/core/router/router-proxy.js:9:17
正如我所说,我尝试了在其他类似问题中找到的不同潜在解决方案(例如这个),但没有一个答案对我有用。
我参加聚会迟到了,但我只是在绞尽脑汁解决这个问题,然后找到了解决方案。
问题可能出在 app.module.ts 中的这一行:
providers: [UsersService, AuthService, PolsService, JwtService],
JwtService 不应添加为提供者。如果这样做,它似乎会重置所有已注册的选项。
您正在将
ConfigModule
导入到 AppModule
中,但不是作为全局模块导入,因此您的 AuthModule
不知道它。这就是为什么它不知道这个秘密。
您也可以将
ConfigModule
导入到 AuthModule
中,或者从 AppModule
中将其作为全局模块导入。
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
...
],
...
})
export class AppModule {}
然后在
AuthModule
中使用 JwtModule
异步注册 registerAsync
。使用一个工厂,在其中注入从 ConfigService
导出的 ConfigModule
。
@Module({
imports: [
UsersModule,
PassportModule,
JwtModule.registerAsync({
useFactory: (configService: ConfigService) => {
return {
secret: configService.get<string>('JWT_SECRET_KEY'),
signOptions: { expiresIn: '60s' },
};
},
inject: [ConfigService],
}),
],
...
})
export class AuthModule {}
在
ConfigModule
中导入的 AppModule
会在异步 I/O 操作中读取 .env
文件。通过异步注册 JwtModule
并注入 ConfigService
依赖项,您将使其等待,直到加载 ConfigModule
并读取 .env
文件。只需使用 ConfigService
读取环境变量并进行转换即可。
有关使用
ConfigService
的更多信息可以在 NestJS 的文档中找到。
https://docs.nestjs.com/techniques/configuration#using-the-configservice
你可以改变
secret: process.env.JWT_SECRET_KEY
到
secret: `${process.env.JWT_SECRET_KEY}`
尝试从 app.module.ts 中的提供程序中删除
JwtService
和 AuthService
。同时从 app.module.ts 中的控制器中删除 AuthController
。
当我遇到同样的错误消息时,这对我有用。虽然我还不完全确定为什么会这样(我对 NestJS 很陌生),但这是我的推理:您将
AuthModule
(已包含
AuthController
和
AuthService
)传递到要导入到
AppModule
中。通过在根 (
AuthController
) 级别再次添加
AuthService
和
AppModule
,我相信您首先就违背了拥有
AuthModule
的目的,并且不使用模块上下文。通过将
JwtService
添加到
AppModule
提供程序,您可以使用空的来覆盖在
JwtService
上下文中注册的
AuthModule
。再次强调,我是 NestJS 的新手,非常欢迎指正。
编辑:
我假设您正在遵循
documentation,不幸的是它没有显示 AppModule。
但是,它们确实链接到 GitHub 存储库,其中仅导入模块(而不是服务):
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AuthModule } from './auth/auth.module';
import { UsersModule } from './users/users.module';
@Module({
imports: [AuthModule, UsersModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
我希望这有帮助。