| AUTH & SECURITY TRONG FASTAPI

Được viết bởi thanhdt vào ngày 26/01/2026 lúc 13:30 | 119 lượt xem

Bạn đã xây dựng xong API, nó chạy nhanh “như gió” nhờ FastAPI. Nhưng khoan đã, liệu nó có an toàn không? Hay bất kỳ ai cũng có thể vào xóa sạch database của bạn?

Bảo mật (Security) là “tấm khiên” không thể thiếu cho bất kỳ hệ thống nào. Trong bài viết này, chúng ta sẽ khám phá cách FastAPI giúp bạn triển khai các cơ chế bảo mật “xịn xò” như OAuth2, JWT, API Key một cách dễ dàng và chuẩn chỉ.

1. Tại sao bảo mật trong FastAPI lại “sướng” đến thế?

Nếu bạn từng làm việc với Flask hay Django, bạn sẽ thấy việc tích hợp Auth thường khá cồng kềnh hoặc phụ thuộc nhiều vào thư viện bên thứ 3.

FastAPI thì khác:

  • Tích hợp sẵn (Built-in Security): Nó hỗ trợ OAuth2, API Key, HTTP Basic Auth ngay từ “trong trứng”.
  • Dependency Injection: Đây là “vũ khí bí mật” giúp code Auth của bạn cực kỳ gọn gàng và tái sử dụng được ở mọi nơi.
  • OpenAPI (Swagger UI): Khi bạn định nghĩa Security, FastAPI tự động thêm nút “Authorize” (cái ổ khóa) vào Swagger UI. Bạn có thể đăng nhập và test API ngay trên trình duyệt mà không cần code thêm dòng nào cho giao diện test.

2. OAuth2 & JWT: Tiêu chuẩn vàng (The Gold Standard)

Đây là cơ chế phổ biến nhất hiện nay cho các ứng dụng hiện đại (SPA, Mobile App).

  • OAuth2: Là giao thức (protocol) quy định cách client xin quyền truy cập.
  • JWT (JSON Web Token): Là định dạng của cái “vé” (token) mà server cấp cho client.

Cơ chế hoạt động đơn giản:

  1. User gửi username + password lên server.
  2. Server kiểm tra, nếu đúng -> Trả về 1 chuỗi Token (JWT).
  3. User lưu Token này (thường ở LocalStorage hoặc Cookie).
  4. Mỗi lần gọi API sau đó, User đính kèm Token này vào Header (Authorization: Bearer <token>).
  5. Server kiểm tra Token. Nếu hợp lệ -> Cho phép thực hiện hành động.
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer

app = FastAPI()

# Khai báo scheme: Client phải gửi token dạng Bearer
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

def get_current_user(token: str = Depends(oauth2_scheme)):
    # Trong thực tế, bạn sẽ verify token (giải mã JWT) ở đây
    if token != "fake-super-secret-token":
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid authentication credentials",
            headers={"WWW-Authenticate": "Bearer"},
        )
    return {"user": "thanhdt"}

@app.get("/users/me")
async def read_users_me(current_user: dict = Depends(get_current_user)):
    return current_user

Bạn thấy sức mạnh của Dependency Injection chưa? Chỉ cần Depends(get_current_user), FastAPI sẽ tự động:

  1. Lấy token từ Header.
  2. Chạy hàm get_current_user để kiểm tra.
  3. Nếu lỗi -> Trả về 401 ngay lập tức.
  4. Nếu ngon -> Truyền user vào biến current_user.

3. API Key: Đơn giản và Hiệu quả

Khi bạn làm API cho các đối tác (Services-to-Services) hoặc các tool nội bộ, API Key là lựa chọn gọn nhẹ hơn OAuth2.

from fastapi.security import APIKeyHeader

API_KEY_NAME = "X-API-Key"
api_key_header = APIKeyHeader(name=API_KEY_NAME, auto_error=True)

async def get_api_key(api_key_header: str = Depends(api_key_header)):
    if api_key_header == "my_secure_api_key":
        return api_key_header
    raise HTTPException(
        status_code=status.HTTP_403_FORBIDDEN,
        detail="Could not validate credentials",
    )

@app.get("/secure-data")
async def get_secure_data(api_key: str = Depends(get_api_key)):
    return {"data": "Top Secret"}

Client chỉ cần gửi Header X-API-Key: my_secure_api_key là xong.

4. Best Practices: Bảo mật “chuẩn chỉnh”

Code chạy được là một chuyện, code an toàn là chuyện khác. Hãy ghi nhớ các nguyên tắc sau:

a. Luôn dùng HTTPS

Không bàn cãi. Nếu không có HTTPS, hacker có thể “nghe lén” được Token hoặc Password của bạn bay giữa đường truyền.

b. Hashing Password (Băm mật khẩu)

KHÔNG BAO GIỜ lưu mật khẩu gốc (plaintext) vào database. Hãy dùng các thuật toán băm mạnh như bcrypt hoặc Argon2.

Thư viện khuyên dùng: passlib kết hợp bcrypt.

from passlib.context import CryptContext

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)

def get_password_hash(password):
    return pwd_context.hash(password)

c. Rate Limiting (Giới hạn lượt gọi)

Đừng để API của bạn bị DDoS sập server. Hãy giới hạn số request mà một IP có thể gọi trong 1 phút. Bạn có thể dùng slowapi hoặc cấu hình ở tầng Nginx/Cloudflare.

Kết luận

FastAPI biến việc bảo mật từ “cơn ác mộng” thành một trải nghiệm khá… dễ chịu. Cơ chế Dependency Injection giúp bạn tách biệt hoàn toàn logic check quyền (Auth) ra khỏi logic nghiệp vụ (Business Logic), giúp code sạch và dễ bảo trì hơn gấp nhiều lần.

Bạn muốn làm chủ Authentication & Security nâng cao?

Trong khóa học Python FastAPI Thực Chiến, mình hướng dẫn chi tiết cách xây dựng hệ thống Login/Register hoàn chỉnh với JWT, Refresh Token, phân quyền (Role-based), và tích hợp Social Login (Google/Facebook).