Giới thiệu
Xây dựng API an toàn là điều cần thiết trong phát triển phần mềm. Dù bạn đang bảo vệ dữ liệu người dùng, bảo mật logic kinh doanh hay quản lý quyền truy cập vào các tính năng cao cấp, xác thực là nền tảng của an ninh ứng dụng của bạn.
Thách thức? Xác thực thường giống như một mê cung phức tạp của các token, phiên làm việc, headers và các giao thức bảo mật. Khi bạn thêm áp lực vào việc chọn phương pháp phù hợp nhất cho trường hợp sử dụng cụ thể của mình, thật dễ dàng để cảm thấy bị choáng ngợp.
Tin vui là: FastAPI đơn giản hóa xác thực, làm cho nó vừa mạnh mẽ vừa thân thiện với người dùng. Với các tính năng bảo mật tích hợp, khả năng tự động tạo tài liệu và cú pháp Python trực quan, bạn có thể triển khai xác thực mạnh mẽ mà không gặp rắc rối.
Trong hướng dẫn này, chúng ta sẽ đi qua ba phương pháp xác thực người dùng chính:
- Xác thực HTTP cơ bản: Thích hợp cho API nội bộ, microservices và nguyên mẫu nhanh.
- Xác thực bằng API key: Được ưa chuộng cho API công cộng, tích hợp bên thứ ba và hệ thống tự động.
- Xác thực dựa trên phiên: Thích hợp cho các ứng dụng web truyền thống và giao diện người dùng.
Cuối cùng, bạn sẽ hiểu không chỉ cách triển khai mỗi phương pháp mà còn biết khi nào nên sử dụng chúng, cùng với các quy tắc bảo mật tốt nhất.
Xác thực vs Ủy quyền
Hai thuật ngữ này thường bị nhầm lẫn. Dưới đây là phân tích nhanh:
- Xác thực giống như việc kiểm tra ID của ai đó ở cửa ra vào. Nó trả lời câu hỏi: “Bạn là ai?”. Khi một người dùng đăng nhập với tên người dùng và mật khẩu của họ, quá trình xác thực diễn ra.
- Ủy quyền giống như việc kiểm tra xem người đó có quyền truy cập VIP hay không. Nó trả lời câu hỏi: “Bạn có quyền làm gì?”. Khi bạn biết ai đó là ai, bạn quyết định xem họ có thể truy cập các tính năng quản trị, xóa bài viết hoặc thậm chí cấp quyền cho người khác hay không.
Hãy nghĩ theo cách này: xác thực giúp bạn vào tòa nhà, ủy quyền xác định các phòng mà bạn có thể vào. FastAPI hỗ trợ cả hai, nhưng chúng ta sẽ tập trung vào xác thực trong bài viết này.
Thiết lập
Hãy bắt đầu với cấu trúc dự án cơ bản và các phụ thuộc:
Tạo một thư mục dự án mới:
bash
mkdir fastapi-auth-demo && cd fastapi-auth-demo
Thiết lập môi trường ảo:
bash
# Tạo môi trường ảo
python -m venv venv
# Kích hoạt nó
./venv/Scripts/activate # Windows
source venv/bin/activate # macOS/Linux
Tạo một requirements.txt và thêm các phụ thuộc sau:
bash
fastapi==0.104.1
uvicorn[standard]==0.24.0
python-multipart==0.0.6
passlib[bcrypt]==1.7.4
python-jose[cryptography]==3.3.0
itsdangerous==2.2.0
Cài đặt các phụ thuộc:
bash
pip install -r ./requirements.txt
Bây giờ hãy tạo ứng dụng FastAPI chính của chúng ta với một số thiết lập cơ bản:
python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI(title="Mô phỏng xác thực FastAPI", version="1.0.0")
# Thêm middleware CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
Xác thực HTTP cơ bản
Xác thực HTTP cơ bản là hình thức xác thực đơn giản nhất, nơi thông tin xác thực (tên người dùng và mật khẩu) được gửi cùng với mỗi yêu cầu. Loại xác thực này phù hợp nhất cho các API nội bộ hoặc nguyên mẫu nhanh.
python
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
import secrets
security = HTTPBasic()
fake_users_db = {
"john": {"username": "john", "password": "secret123", "role": "user"},
"admin": {"username": "admin", "password": "supersecret", "role": "admin"}
}
def authenticate_user(credentials: HTTPBasicCredentials = Depends(security)):
user = fake_users_db.get(credentials.username)
if not user or not secrets.compare_digest(credentials.password, user["password"]):
raise HTTPException(status_code=401, detail="Thông tin xác thực không hợp lệ")
return user
@app.get("/basic/profile")
def read_profile(user: dict = Depends(authenticate_user)):
return {"message": f"Chào mừng {user['username']}!"}
@app.get("/basic/admin")
def admin_area(user: dict = Depends(authenticate_user)):
if user["role"] != "admin":
raise HTTPException(status_code=403, detail="Chỉ dành cho quản trị viên")
return {"message": "Bạn đang ở khu vực quản trị."}
Xác thực bằng API Key
Xác thực bằng API key rất phổ biến cho việc truy cập API, nơi các client bao gồm một key trong headers hoặc tham số truy vấn. Thay vì gửi tên người dùng và mật khẩu cho mỗi yêu cầu, các client gửi một key đặc biệt xác định họ.
python
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
api_key_header = HTTPBearer()
fake_api_keys = {
"sk_test_123": {"key_id": "1", "permissions": ["read", "write"]},
"sk_live_456": {"key_id": "2", "permissions": ["read"]}
}
def validate_api_key(credentials: HTTPAuthorizationCredentials = Depends(api_key_header)):
key = credentials.credentials
if key not in fake_api_keys:
raise HTTPException(status_code=401, detail="API Key không hợp lệ")
return fake_api_keys[key]
@app.get("/apikey/data")
def read_data(api_key=Depends(validate_api_key)):
return {"data": ["item1", "item2"]}
@app.post("/apikey/create")
def create_item(item: dict, api_key=Depends(validate_api_key)):
if "write" not in api_key["permissions"]:
raise HTTPException(status_code=403, detail="Cần quyền ghi")
return {"message": "Đã tạo item", "item": item}
Xác thực dựa trên phiên
Xác thực dựa trên phiên lưu trữ trạng thái người dùng trên máy chủ và sử dụng cookie phiên cho các yêu cầu tiếp theo. Khi bạn đăng nhập, máy chủ tạo một phiên và cung cấp cho bạn một cookie. Nó giống như việc nhận một vòng tay tại một buổi hòa nhạc — miễn là bạn có nó, bạn có thể tự do di chuyển.
python
from fastapi import FastAPI, Request, Form, Depends, HTTPException, status
from fastapi.responses import JSONResponse
from starlette.middleware.sessions import SessionMiddleware
from pydantic import BaseModel
# Thêm middleware phiên
app.add_middleware(SessionMiddleware, secret_key="super-secret-session-key")
# Cơ sở dữ liệu người dùng mô phỏng
users_db = {
"alice": "password123",
"bob": "securepass"
}
class LoginSchema(BaseModel):
username: str
password: str
@app.post("/login")
async def login(request: Request, payload: LoginSchema):
username = payload.username
password = payload.password
if username in users_db and users_db[username] == password:
request.session["user"] = username
return JSONResponse({"message": "Đăng nhập thành công"})
raise HTTPException(status_code=401, detail="Thông tin xác thực không hợp lệ")
@app.get("/dashboard")
async def dashboard(request: Request):
user = request.session.get("user")
if not user:
raise HTTPException(status_code=401, detail="Chưa xác thực")
return {"message": f"Chào mừng đến bảng điều khiển của bạn, {user}!"}
@app.post("/logout")
async def logout(request: Request):
request.session.clear()
return {"message": "Đăng xuất thành công"}
Xử lý lỗi
Bài viết này đi sâu vào các phản hồi HTTP khác nhau và các kỹ thuật xử lý lỗi của chúng. Việc xử lý lỗi nhất quán cải thiện bảo mật và trải nghiệm người dùng:
python
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
@app.exception_handler(HTTPException)
async def http_exception_handler(request, exc):
"""Bộ xử lý ngoại lệ HTTP tùy chỉnh"""
return JSONResponse(
status_code=exc.status_code,
content={
"error": {
"message": exc.detail,
"type": "authentication_error" if exc.status_code == 401 else "authorization_error",
"status_code": exc.status_code
}
},
headers=exc.headers
)
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
"""Xử lý lỗi xác thực"""
return JSONResponse(
status_code=422,
content={
"error": {
"message": "Lỗi xác thực",
"type": "validation_error",
"details": exc.errors()
}
}
)
Các quy tắc bảo mật tốt nhất
1. Không bao giờ lưu trữ mật khẩu dưới dạng văn bản thuần, luôn mã hóa mật khẩu bằng bcrypt:
python
from passlib.context import CryptContext
# Sử dụng mã hóa mật khẩu đúng cách
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def hash_password(password: str) -> str:
return pwd_context.hash(password)
2. Giới hạn tốc độ
python
from collections import defaultdict
import time
# Giới hạn tốc độ đơn giản (sử dụng Redis trong sản xuất)
request_counts = defaultdict(list)
def rate_limit(max_requests: int = 100, window_minutes: int = 15):
def decorator(func):
def wrapper(*args, **kwargs):
client_ip = "127.0.0.1"
now = time.time()
window_start = now - (window_minutes * 60)
# Xóa các yêu cầu cũ
request_counts[client_ip] = [
req_time for req_time in request_counts[client_ip]
if req_time > window_start
]
if len(request_counts[client_ip]) >= max_requests:
raise HTTPException(
status_code=429,
detail="Giới hạn tốc độ đã vượt quá"
)
request_counts[client_ip].append(now)
return func(*args, **kwargs)
return wrapper
return decorator
3. Sử dụng biến môi trường cho các bí mật, với cài đặt pydantic. Không bao giờ mã hóa các khóa bí mật trong mã của bạn:
python
# config.py
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
secret_key: str = "your-secret-key-here"
algorithm: str = "HS256"
access_token_expire_minutes: int = 30
class Config:
env_file = ".env"
settings = Settings()
Kết luận
Chúng ta đã đề cập đến ba chiến lược xác thực trong FastAPI:
- Xác thực HTTP cơ bản: Đơn giản nhưng phù hợp cho các API nội bộ.
- Xác thực bằng API key: Tuyệt vời cho các API công cộng và giao tiếp giữa các dịch vụ.
- Xác thực dựa trên phiên: Cách tiếp cận truyền thống và dựa trên cookie.
Mỗi phương pháp có trường hợp sử dụng riêng, và sự lựa chọn phụ thuộc vào yêu cầu của ứng dụng của bạn.
Những điều cần lưu ý:
- Luôn sử dụng HTTPS trong sản xuất.
- Mã hóa mật khẩu đúng cách với bcrypt hoặc tương tự.
- Triển khai xử lý lỗi và ghi nhật ký đúng cách.
- Thêm các headers và middleware bảo mật.
- Kiểm tra xác thực của bạn một cách kỹ lưỡng.
- Thêm giới hạn tốc độ cho các API công cộng.
- Sử dụng biến môi trường để lưu trữ dữ liệu nhạy cảm.
Khám phá sâu hơn
- Cách bảo mật API
- Xác thực và ủy quyền với FastAPI
- Các quy tắc bảo mật tốt nhất
- Xác thực HTTP đơn giản
Chúc bạn có một ngày tuyệt vời!!!
Tác giả: Jane Nkwor
Cảm ơn bạn đã trở thành một phần của cộng đồng
Trước khi bạn đi:
Khi nào bạn sẵn sàng
Có 4 cách chúng tôi có thể giúp bạn trở thành một kỹ sư backend tuyệt vời:
- Nền tảng MB: Tham gia hàng ngàn kỹ sư backend học về kỹ thuật backend. Xây dựng các dự án backend thực tế, học từ các khóa học và lộ trình đã được kiểm duyệt bởi chuyên gia, theo dõi việc học của bạn và thiết lập lịch trình, và giải quyết các nhiệm vụ, bài tập, và thử thách về kỹ thuật backend.
- Học viện MB: "Học viện MB" là một khóa học 6 tháng tập trung vào Kỹ thuật Backend Nâng cao để sản xuất ra các kỹ sư backend tuyệt vời.
- Tham gia Backend Weekly: Nếu bạn thích các bài viết như thế này, bạn chắc chắn sẽ thích bản tin hàng tuần độc quyền của chúng tôi, chia sẻ tài nguyên kỹ thuật backend độc quyền để giúp bạn trở thành một Kỹ sư Backend tuyệt vời.
- Tìm việc làm Backend: Tìm hơn 2.000+ công việc Backend Quốc tế từ xa được tùy chỉnh hoặc tiếp cận 50.000+ kỹ sư backend trên bảng việc làm Kỹ thuật Backend số 1.
Được xuất bản lần đầu tại https://masteringbackend.com vào ngày 2 tháng 9 năm 2025.