Guards määrittävät, onko pyyntö sallittu jatkaa reitinkäsittelijään — ne ovat NestJS:n omistautunut mekanismi valtuutukselle (ja usein myös todentamiselle). Guard palauttaa true pyynnön sallimiseksi tai false/heittää poikkeuksen sen estämiseksi.
Guards määrittävät, onko pyyntö sallittu jatkaa reitinkäsittelijään — ne ovat NestJS:n omistautunut mekanismi valtuutukselle (ja usein myös todentamiselle). Guard palauttaa true pyynnön sallimiseksi tai false/heittää poikkeuksen sen estämiseksi.
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
return !!request.headers.authorization; // true = allow, false = block (403)
}
}
Guard toteuttaa canActivate():n, joka palauttaa boolen (tai sen Promise/Observable). false palauttaminen estää pyynnön 403-virheellä; voit myös heittää tietyn poikkeuksen (esim. UnauthorizedException).
@UseGuards(AuthGuard) // on a single route
@Get("profile")
getProfile() {}
@UseGuards(AuthGuard) // on a whole controller (all routes)
@Controller("admin")
export class AdminController {}
app.useGlobalGuards(new AuthGuard()); // globally (all routes)
Guardia voidaan soveltaa metodin, kontrollerin tai globaalilla tasolla.
@Injectable()
export class JwtAuthGuard implements CanActivate {
constructor(private jwtService: JwtService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const token = request.headers.authorization?.split(" ")[1];
if (!token) throw new UnauthorizedException();
try {
request.user = await this.jwtService.verifyAsync(token); // attach the user
return true;
} catch {
throw new UnauthorizedException("Invalid token");
}
}
}
// a @Roles decorator stores required roles as metadata
@Roles("admin")
@Get("users")
listUsers() {}
// the RolesGuard reads the metadata and checks the user's roles
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(ctx: ExecutionContext): boolean {
const roles = this.reflector.get<string[]>("roles", ctx.getHandler());
const { user } = ctx.switchToHttp().getRequest();
return roles.some(role => user.roles?.includes(role)); // allow if the user has a required role
}
}
@Roles()-dekoraattorin (metatieto) yhdistäminen guardin kanssa, joka lukee sen (Reflector kautta), on standardimallia roolipohjaisen pääsynvalvontaan.
The ExecutionContext gives guards rich info (the handler, class, request) — more
than plain middleware — which is why guards (not middleware) are the right place
for authorization decisions.
Guardit ovat NestJS:n omistautettu, idiomaalinen mekanismi valtuutukselle — kontrolli siitä, mitkä pyynnöt saavat kulkea käsittelijöihin todentamisen ja oikeuksien perusteella.
Niiden ymmärtäminen on olennaista, koska käytännöllisesti katsoen jokainen todellinen sovellus joutuu suojaamaan reittejä (vaatia kirjautuminen, tarkistaa roolit/oikeudet), ja guardit ovat oikea työkalu siihen (paljon siistimpi kuin todentamislogiikan työntäminen middleware:hen tai jokaiseen käsittelijään).
Standardimallit — JWT/auth-guard, joka vahvistaa tunnistetiedot ja liittää käyttäjän pyyntöön, ja roolipohjaiset guardit, jotka yhdistävät @Roles()-dekoraattorin Reflector-lukevaan guardiin RBAC:lle — ovat perusedellytyksiä NestJS-sovellusten suojaamiselle.
Guardien pääsy rikkaaseen ExecutionContext:iin (kohde-käsittelijän, luokan ja pyynnön tunteminen) on juuri se, mikä tekee niistä sopivia valtuutuspäätöksiin, joita middleware ei voi siististi tehdä.
Osaaminen siitä, miten kirjoitetaan, sovelletaan (metodi/ohjain/globaalisti) ja yhdistetään guardia metatieto-dekoraattoreihin, on ytimen osaamista turvallisten NestJS-sovellusten rakentamiseen ja on usein esiintyvä, arkkitehtuurisesti tärkeä aihe kehyksessä.