javascript - NestJS - Kuinka käyttää RoleGuardia JWT:n kanssa?
Tällä hetkellä olen onnistunut käyttämään AuthGuardia JWT-todennuksella, mutta en onnistu saamaan käyttäjää Roolit-kohdassa.
Olen yrittänyt seurata kissan esimerkkiä, mutta en koskaan saa user-oliota määriteltyä, kuten näet rivillä 14.
Tässä on koodini:
// auth.controller.ts
@Controller('auth')
@UseGuards(RolesGuard)
export class AuthController {
constructor(private readonly authService: AuthService) {}
@Get('token')
async createToken(): Promise<any> {
return await this.authService.createToken();
}
@Post()
@UseGuards(AuthGuard())
@Roles('admin')
findAll() {
// this route is restricted by AuthGuard
// JWT strategy
return 'Super important info';
}
}
// auth.module.ts
@Module({
imports: [
SharedModule,
PassportModule.register({ defaultStrategy: 'jwt' }),
JwtModule.registerAsync({
imports: [SharedModule],
useFactory: async (configService: ConfigService) => ({
secretOrPrivateKey: configService.get('SECRET_KEY'),
signOptions: {
expiresIn: configService.get('SECRET_KEY_EXPIRES'),
},
}),
inject: [ConfigService],
}),
],
controllers: [AuthController],
providers: [
AuthService,
JwtStrategy,
],
})
export class AuthModule {}
Kaikki muu on tarkalleen kuten esimerkissä säilytyspaikassa. Onko mitään ideaa, miten voisi saada määriteltyä users?
Vastaus #1
AuthGuard() täytyy suorittaa ennen RolesGuard-ohjainta, jotta olet todennettu ja user-ominaisuus on asetettu.
Tietääkseni ei ole muuta tapaa muuttaa vartijoidensi järjestystä kuin määrittelemällä ne seuraavasti:
@UseGuards(AuthGuard(), RolesGuard)
Tässä asiassa käydään keskustelua mahdollisesta API:sta vartijoiden suoritushierarkian muuttamiseksi.
Tässä asiassa mainitaan vaihtoehtoinen ratkaisu:
Tässä käyttötapauksessa tuntuu siltä, että todennuslogiikan laittaminen middlewareen olisi parempi, koska se suoritetaan ennen vartijaa.
Vastaus #2
Tämä toimi minulle
jwt.guard.ts
import { AuthGuard } from '@nestjs/passport';
export class JwtGuard extends AuthGuard('jwt') {
constructor() {
super();
}
}
app.module.ts
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
],
providers: [
{
provide: APP_GUARD,
useClass: JwtGuard,
},
{
provide: APP_GUARD,
useClass: RoleGuard,
},
],
})
export class AppModule {}
rooli.decorator.ts
import { SetMetadata } from '@nestjs/common';
import { Role } from 'common/enums';
export const ROLE_KEY = 'role';
export const AllowRole = (role: Role) => SetMetadata(ROLE_KEY, role);
rooli.vartija.ts
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { ROLE_KEY } from 'common/decorators';
import { Role } from 'common/enums';
@Injectable()
export class RoleGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const requiredRole = this.reflector.getAllAndOverride<Role>(ROLE_KEY, [
context.getHandler(),
context.getClass(),
]);
if (!requiredRole) {
return true;
}
const { user } = context.switchToHttp().getRequest();
console.log({ requiredRole });
console.log({ user });
return user.role === requiredRole;
}
}
