Quangkhoi1228 | Knowledge base
  • Về trang chủ
  • Lời nói đầu
  • Nhập môn lập trình web
    • Giáo trình
    • Class 01: Hello HTML!!!
    • Class 02: HTML: Comment, Text formatting, Attribute, Link
    • Class 03: HTML: Style, Inline/Block element, Image
    • Class 04: HTML: List, Table, Responsive
    • Class 05: Hello CSS!!!
    • Class 06: CSS: Flexbox, Layout
    • Class 07: Hello Javascript!!!
    • Class 08: JS: Operator, Expression, For/While Loop, Function
    • Class 09: JS: Search Function
    • Project 1: Layout Structure
    • Project 2: Search Function
    • Project 3: MVP
    • Review "Lập trình Frontend Website"
  • Lập trình Frontend Website
    • Class 01: Ôn tập HTML
    • Class 02: Thảo luận HTML
    • Class 03: Ôn tập CSS
    • Class 04: Chrome dev tools, CSS Box Model
    • Class 05: CSS: Position, Đơn vị đo
    • Class 06: CSS: hiệu ứng, responsive
    • Class 07: Thảo luận CSS
    • Class 08: Ôn tập JS
    • Class 09: JS: Mảng, Đối tượng, Biến tham chiếu và tham trị
    • Class 10: JS: Class, Pair programming
    • Class 11: JS: DOM, UI Rendering
  • Lập trình ReactJS
    • Class 01: Giới thiệu ReactJS
    • Class 01: Tạo dự án ReactJS mới
    • Class 02: ReactJS Component
    • Class 02: Import/Export component
    • Class 03: useState hook
    • Class 04: Project 1: UI cơ bản
    • Class 05: Render có điều kiện và danh sách
    • Class 06: useEffect hook
    • Class 07: Project 2: Xử lý user logic
    • Class 08: Project 3: Hoàn thiện dashboard
    • Class 09: Form và dữ liệu người dùng
    • Class 10: UseRef và thao tác với DOM
    • Class 11: Project 4: Xử lý form data
    • Class 12: Project 5: Hoàn thiện form data
    • Class 13: useMemo và useCallback
    • Class 14: Custom Hook
    • Class 15: Project 6: Hoàn thiện project
    • Class 16: Ôn tập
  • Lập trình NestJS
    • Class 01: Giới thiệu NestJS & Cài đặt dự án
    • Class 02: Routing, Controller và Dependency Injection
    • Class 03: Service và Data Validation
    • Class 04: Kết nối Database với TypeORM
    • Class 05: Quan hệ trong Database (OneToMany, ManyToOne) với TypeORM
    • Class 06: Middleware, Interceptor, Guard
    • Class 07: Authentication – JWT
    • Class 08: Authorization – Phân quyền
    • Class 09: File Upload & Configuration
    • Class 10: Giới thiệu WebSocket
    • Class 11: Project 1
    • Class 12: Project 2
    • Class 13: Project 3
    • Class 14: Project 4
    • Class 15: Project 5
    • Class 16: Project 6
  • Lập trình Java cơ bản
    • Class 01: Khai giảng
    • Class 02: Hello Java
    • Class 03: Biến và kiểu dữ liệu
    • Class 04: Toán tử và biểu thức
    • Class 05: Câu lệnh điều kiện
    • Class 06: Review 1
    • Class 07: Vòng lặp For
    • Class 08: Vòng lặp While / Do-while
    • Class 09: Java Method
    • Class 10: Review 2
    • Class 11: Java User Input
    • Class 12: Java File
    • Class 13: Final Exam 1
    • Class 14: Final Exam 2
    • Review "Lập trình OOP với Java"
  • Lập trình OOP với Java
    • Class 01: Hello OOP
    • Class 02: Class Attribute và Method
    • Class 03: Constructor, Modifier và Package
    • Class 04: Review 1
    • Class 05: Tính kế thừa và đa hình
    • Class 06: Tính trừu tượng và đóng gói
    • Class 07: Review 2
    • Class 08: Final Exam 1
    • Class 09: Final Exam 2
    • Review "CTDL và Giải thuật với Java"
  • CTDL và Giải thuật với Java
    • Class 01: Hello Data Structure
  • HTML
    • Cài đặt công cụ cơ bản
    • HTML là gì?
    • Phần tử HTML
    • Cấu trúc file HTML cơ bản
    • Comment trong HTML
    • Format văn bản trong HTML
    • Thuộc tính HTML
    • Liên kết(link) trong HTML
    • Project: Professional Email
    • HTML Style
    • Phần tử Inline và Block
    • HTML Image
    • HTML List
    • HTML Table
    • Head trong HTML
    • HTML Responsive
    • Project: Online Cover Letter
  • CSS
    • Giới thiệu CSS
    • CSS Selector
    • Thêm CSS vào trang
    • Comment trong CSS
    • Màu sắc trong CSS
    • CSS Background
    • CSS Border
    • CSS Spacing
    • CSS Flexbox
    • HTML Layout
    • Chrome dev tools
    • CSS Box Model
    • CSS Position
    • Đơn vị đo trong CSS
    • CSS Pseudo-classes
    • CSS Responsive
  • JavaScript
    • Giới thiệu Javascript
    • Thêm JS vào trang
    • Các hàm có sẵn
    • Biến và kiểu dữ liệu
    • JS Mảng
    • JS Đối tượng
    • JS Biến Tham Chiếu và Tham Trị
    • Toán tử và biểu thức
    • Câu lệnh điều kiện
    • Vòng lặp For / While
    • Hàm (Function)
    • Chức năng tìm kiếm với JS và DOM
    • JS Class
    • JS DOM
    • JS Dom Rendering
  • Java
    • Giới thiệu Java
    • Chương trình Hello world
    • Phân biệt JVM, JRE, JDK
    • Java Comment
    • Biến trong Java
    • Kiểu dữ liệu trong Java
    • Java Array
    • Toán tử trong Java
    • Biễu thức trong Java
    • Java If-else
    • Java Switch
    • Vòng lặp For trong Java
    • Vòng lặp While trong Java
    • Vòng lặp Do-while trong Java
    • Java Method
    • Java OOP
    • Java Class và Object
    • Java Class attribute
    • Java Class method
    • Java Constructor
    • Java Modifier
    • Java Package
    • Java Tính kế thừa
    • Java Tính đa hình
    • Java Tính trừu tượng
    • Java Tính đóng gói
    • Java User Input
    • Java File
  • Soft skills
    • Pair Programming
  • Web design and wireframe
  • NextJS
    • Tạo dự án NextJS mới
  • NestJS
    • Giới thiệu NestJS
    • NestJS controller
    • NestJS module
  • Git
    • Setup SSH key với GitHub
  • Bash
    • Giới thiệu Bash/Shell Script
  • Wordpress
    • Thêm custom routes
    • Deploy with ubuntu
  • Deployment
    • SSH server, đổi password và add SSH key
    • Tạo user mới và add SSH key
    • Page
  • GitBook
    • Custom domain with CloudFlare
  • Hướng dẫn khác
    • Gitbook custom domain with Cloudflare
    • Cấu hình OpenVPN
    • Cấu hình và lấy SSH key
    • Công cụ lập trình
      • Visual Studio Code
      • Cài đặt IntelliJ IDEA
    • Đường dẫn file trong HTML
    • CI/CD github action
  • Project: CV online
Powered by GitBook
On this page
  • Xác thực với JWT
  • JWT là gì?
  • Quy trình xác thực JWT
  • Các bước cài đặt JWT trong NestJS
  • Đăng ký, đăng nhập, mã hóa mật khẩu bằng bcrypt
  • Mã hóa mật khẩu
  • Ví dụ mã hóa mật khẩu
  • Đăng ký (Register) – lưu user với mật khẩu đã mã hóa
  • Sử dụng Passport.js với chiến lược JWT
  • Passport là gì?
  • Cấu hình chiến lược JWT với Passport
  • Tạo AuthService để xử lý đăng nhập và tạo JWT
  • Bảo vệ route bằng Guard Passport JWT
  • Thực hành: Xây dựng hệ thống auth cơ bản
  • Bước 1: Tạo module auth
  • Bước 2: Cài đặt và cấu hình JWT module
  • Bước 3: Viết Controller xử lý đăng ký, đăng nhập
  • Bước 4: Bảo vệ route bằng JwtAuthGuard
  • Bài tập thực hành
  • Tổng kết
  1. Lập trình NestJS

Class 07: Authentication – JWT

Authentication (xác thực) là bước quan trọng để đảm bảo người dùng truy cập vào hệ thống một cách an toàn và có quyền hạn phù hợp. JWT (JSON Web Token) là một tiêu chuẩn phổ biến để thực hiện xác thực không trạng thái (stateless authentication).


Xác thực với JWT

JWT là gì?

JWT là một chuỗi gồm 3 phần: header, payload, và signature, dùng để truyền tải thông tin xác thực giữa client và server một cách an toàn. Token này có thể được gửi trong header Authorization của HTTP request.

Quy trình xác thực JWT

  • Người dùng đăng nhập (login) bằng username/password.

  • Server kiểm tra thông tin, nếu đúng sẽ tạo ra JWT chứa payload (ví dụ userId).

  • Client lưu token và gửi trong các request tiếp theo.

  • Server dùng secret key để xác thực token, cho phép truy cập tài nguyên bảo vệ.

Các bước cài đặt JWT trong NestJS

  • Cài đặt các package: @nestjs/jwt, passport-jwt, bcrypt

npm install @nestjs/jwt passport-jwt bcrypt
npm install --save-dev @types/bcrypt

Đăng ký, đăng nhập, mã hóa mật khẩu bằng bcrypt

Mã hóa mật khẩu

  • bcrypt giúp mã hóa mật khẩu người dùng trước khi lưu vào database.

  • Hàm hash() tạo mật khẩu mã hóa.

  • Hàm compare() so sánh mật khẩu người dùng nhập với mật khẩu đã mã hóa.

Ví dụ mã hóa mật khẩu

import * as bcrypt from 'bcrypt';

async function hashPassword(password: string): Promise<string> {
  const saltRounds = 10;
  return await bcrypt.hash(password, saltRounds);
}

async function comparePassword(password: string, hash: string): Promise<boolean> {
  return await bcrypt.compare(password, hash);
}

Đăng ký (Register) – lưu user với mật khẩu đã mã hóa

async registerUser(username: string, password: string) {
  const hashedPassword = await this.hashPassword(password);
  const user = this.userRepository.create({ username, password: hashedPassword });
  await this.userRepository.save(user);
  return user;
}

Sử dụng Passport.js với chiến lược JWT

Passport là gì?

Passport là middleware hỗ trợ đa dạng các chiến lược xác thực (OAuth, JWT, local...). NestJS tích hợp Passport rất tốt, giúp xây dựng hệ thống auth đơn giản và rõ ràng.

Cấu hình chiến lược JWT với Passport

// auth/jwt.strategy.ts
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: 'your_jwt_secret_key', // nên để trong biến môi trường
    });
  }

  async validate(payload: any) {
    // payload chứa dữ liệu user đã encode trong token
    return { userId: payload.sub, username: payload.username };
  }
}

Tạo AuthService để xử lý đăng nhập và tạo JWT

// auth/auth.service.ts
import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import * as bcrypt from 'bcrypt';

@Injectable()
export class AuthService {
  constructor(private jwtService: JwtService) {}

  async validateUser(username: string, pass: string): Promise<any> {
    // Giả sử fetch user từ db
    const user = await this.findUserByUsername(username);
    if (user && (await bcrypt.compare(pass, user.password))) {
      const { password, ...result } = user;
      return result;
    }
    return null;
  }

  async login(user: any) {
    const payload = { username: user.username, sub: user.userId };
    return {
      access_token: this.jwtService.sign(payload),
    };
  }
  
  // Ví dụ giả định
  private async findUserByUsername(username: string) {
    // Tìm user trong db
  }
}

Bảo vệ route bằng Guard Passport JWT

// auth/jwt-auth.guard.ts
import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}

Sử dụng Guard trong controller:

import { UseGuards } from '@nestjs/common';
import { JwtAuthGuard } from './auth/jwt-auth.guard';

@UseGuards(JwtAuthGuard)
@Get('profile')
getProfile() {
  return { message: 'Đây là dữ liệu bảo vệ bằng JWT' };
}

Thực hành: Xây dựng hệ thống auth cơ bản

Bước 1: Tạo module auth

nest g module auth
nest g service auth
nest g controller auth

Bước 2: Cài đặt và cấu hình JWT module

// auth/auth.module.ts
import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { AuthService } from './auth.service';
import { JwtStrategy } from './jwt.strategy';

@Module({
  imports: [
    PassportModule,
    JwtModule.register({
      secret: 'your_jwt_secret_key', // môi trường thật phải dùng env
      signOptions: { expiresIn: '60m' },
    }),
  ],
  providers: [AuthService, JwtStrategy],
  exports: [AuthService],
})
export class AuthModule {}

Bước 3: Viết Controller xử lý đăng ký, đăng nhập

// auth/auth.controller.ts
import { Controller, Post, Body, UnauthorizedException } from '@nestjs/common';
import { AuthService } from './auth.service';

@Controller('auth')
export class AuthController {
  constructor(private authService: AuthService) {}

  @Post('register')
  async register(@Body() body: { username: string; password: string }) {
    return this.authService.registerUser(body.username, body.password);
  }

  @Post('login')
  async login(@Body() body: { username: string; password: string }) {
    const user = await this.authService.validateUser(body.username, body.password);
    if (!user) throw new UnauthorizedException('Sai tên đăng nhập hoặc mật khẩu');
    return this.authService.login(user);
  }
}

Bước 4: Bảo vệ route bằng JwtAuthGuard

// users/users.controller.ts
import { Controller, Get, UseGuards } from '@nestjs/common';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';

@Controller('users')
export class UsersController {
  @UseGuards(JwtAuthGuard)
  @Get('profile')
  getProfile() {
    return { message: 'Dữ liệu chỉ dành cho user đã đăng nhập' };
  }
}

Bài tập thực hành

  • Cài đặt module auth theo hướng dẫn

  • Viết endpoint đăng ký (register) và đăng nhập (login)

  • Sử dụng bcrypt để mã hóa mật khẩu khi đăng ký

  • Sử dụng JWT để tạo token khi đăng nhập thành công

  • Viết route bảo vệ bằng JwtAuthGuard

  • Dùng Postman test:

    • Đăng ký user mới

    • Đăng nhập để lấy token

    • Gửi token trong header Authorization: Bearer <token> để truy cập route bảo vệ


Tổng kết

  • JWT là chuẩn xác thực phổ biến, hỗ trợ xây dựng hệ thống auth không trạng thái

  • bcrypt mã hóa mật khẩu giúp bảo mật thông tin người dùng

  • NestJS tích hợp Passport.js giúp dễ dàng tạo chiến lược JWT

  • Cần kết hợp middleware, guard để đảm bảo an toàn cho API

PreviousClass 06: Middleware, Interceptor, GuardNextClass 08: Authorization – Phân quyền

Last updated 3 days ago