Guard ตัดสินว่า request ได้รับอนุญาตให้ดำเนินต่อ ไปยัง route handler หรือไม่ — เป็นกลไกเฉพาะของ NestJS สำหรับ authorization (และมักรวมถึงการตรวจสอบ authentication) Guard ส่งค่า true เพื่ออนุญาต request หรือ false/throw เพื่อบล็อกมัน
@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 implement canActivate() ซึ่งส่งค่า boolean กลับ (หรือ Promise/Observable ของมัน) การส่ง false บล็อก request ด้วย 403; คุณยังสามารถ throw exception ที่เจาะจงได้ (เช่น 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)
Guard สามารถใช้ได้ในระดับ method, controller หรือ global
@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
}
}
การรวม decorator @Roles() (metadata) กับ guard ที่อ่านมัน (ผ่าน Reflector) เป็นรูปแบบมาตรฐานสำหรับ role-based access control
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.
Guard เป็นกลไกเฉพาะและตามแบบฉบับของ NestJS สำหรับ authorization — ควบคุมว่า request ใดได้รับอนุญาตให้ถึง handler โดยอิงจาก authentication และสิทธิ์
การเข้าใจมันเป็นสิ่งจำเป็นเพราะแทบทุกแอปพลิเคชันจริงต้องปกป้อง route (กำหนดให้ต้อง login, ตรวจสอบ role/สิทธิ์) และ guard เป็นเครื่องมือ ที่ถูกต้อง สำหรับสิ่งนี้ (สะอาดกว่าการยัด logic ของ auth ลงใน middleware หรือแต่ละ handler มาก)
รูปแบบมาตรฐาน — guard JWT/auth ที่ตรวจสอบ credential และแนบ user เข้ากับ request และ guard ตาม role ที่รวม decorator @Roles() กับ guard ที่อ่านผ่าน Reflector สำหรับ RBAC — เป็นพื้นฐานของการรักษาความปลอดภัยให้ API NestJS
การที่ guard เข้าถึง ExecutionContext ที่อุดมข้อมูล (รู้ handler, คลาส และ request เป้าหมาย) คือสิ่งที่ทำให้มันเหมาะกับการตัดสินใจ authorization ที่ middleware ทำไม่ได้อย่างสะอาด
การรู้วิธีเขียน, ใช้ (method/controller/global) และรวม guard กับ metadata decorator เป็นความรู้หลักสำหรับการสร้างแอปพลิเคชัน NestJS ที่ปลอดภัย และเป็นหัวข้อที่พบบ่อยและสำคัญทางสถาปัตยกรรมในเฟรมเวิร์ก