API Design phải biết dành cho website developer
1. Ký số (Signature)
-
Khái niệm: Để ngăn chặn dữ liệu trong API bị giả mạo, chúng ta thường phải triển khai cơ chế ký số cho API.
-
Cách hoạt động:
- Bên phía requester:
- Ghép các tham số
request
,timestamp
vàsecret key
thành một chuỗi. - Tạo chữ ký (
sign
) bằng thuật toánhash
nhưMD5
. - Gửi chữ ký này trong request parameters hoặc headers.
- Ghép các tham số
- Bên phía API gateway:
- Lấy giá trị
sign
từ request. - Dùng cùng các tham số
request
,timestamp
vàsecret key
để tạo một chữ ký mới. - So sánh hai giá trị
sign
. - Nếu khớp -> request hợp lệ, tiếp tục xử lý.
- Nếu không khớp -> trả về lỗi chữ ký không hợp lệ.
- Lấy giá trị
- Bên phía requester:
-
Tại sao cần timestamp trong chữ ký?
- Tránh replay attack (gửi lại request cũ).
- Giảm nguy cơ bị
brute-force
dò secret key. - Thường giới hạn thời gian hiệu lực request (VD: 15 phút).
-
Cách tạo secret key:
- Dùng private key cố định: Cả client & server dùng chung một secret key cố định.
- Dùng cặp AK/SK:
Client gửi AK trong request header.
Server tra cứu SK theo AK rồi dùng để kiểm tra chữ ký.
2. Mã hóa dữ liệu
-
Khái niệm: Với dữ liệu nhạy cảm (password, số thẻ ngân hàng, số tiền giao dịch...), không thể gửi dưới dạng plaintext qua internet.
-
Usecase:
-
Ex: API đăng ký tài khoản:
- Frontend: Mã hóa mật khẩu bằng AES với public key.
- Backend: Giải mã bằng secret key, xử lý đăng ký, rồi lưu vào DB với cơ chế mã hóa khác (VD: bcrypt).
-
3. Danh sách IP cho phép (IP Whitelisting)
-
Khái niệm: Giả sử chữ ký API hoặc mã hóa bị lộ, kẻ tấn công vẫn phải gửi request từ một IP hợp lệ.
-
Cách triển khai:
- Chỉ cho phép request từ các IP trong danh sách whitelist. Nếu IP không hợp lệ -> từ chối request ngay lập tức.
- Lưu ý: Nếu server nội bộ bị xâm nhập, hacker vẫn có thể gửi request từ IP hợp lệ.
- Giải pháp bổ sung: Sử dụng Web Firewall (VD: ModSecurity).
4. Giới hạn tốc độ (Rate Limiting)
-
Khái niệm: API phải giới hạn số request để tránh bị spam gây quá tải.
-
Các cách giới hạn phổ biến:
- Giới hạn theo IP: Ví dụ mỗi IP tối đa 10.000 request/phút.
- Giới hạn theo endpoint: Ví dụ một IP chỉ được gọi 2.000 request/phút vào một API cụ thể.
- Giới hạn theo AK/SK: Ví dụ một user với AK/SK chỉ được gọi 10.000 request/phút.
-
Triển khai với:
- Nginx (limit_req_module)
- Redis (rate limiting với Lua script)
- API Gateway
5. Kiểm tra tham số (Parameter Validation)
-
Khái niệm: Mọi request API đều phải kiểm tra tham số đầu vào để tránh lỗi hoặc tấn công dữ liệu.
-
Ví dụ cần kiểm tra:
- Trường bắt buộc không được để trống.
- Kiểu dữ liệu (string, int, date...).
- Độ dài tối đa.
- Giá trị hợp lệ cho các trường enum.
-
Sai sót phổ biến:
- Giá trị amount chấp nhận số âm -> gây lỗi tài chính.
- Trường status nhận giá trị không xác định -> lỗi logic hệ thống.
6. Chuẩn hóa format response
-
Khái niệm: Response API phải có format thống nhất, tránh gây khó khăn cho người tích hợp.
-
Ví dụ xấu:
{ "rt": 10, "errorMgt": "No permission", "result": null }
-
Cách đúng:
{ "code": 403, "message": "No permission", "data": null }
=> Giữ format code + message + data cố định cho mọi response.
7. Xử lý lỗi thống nhất
-
Khái niệm: API không bao giờ được trả về lỗi hệ thống chi tiết, tránh lộ thông tin nhạy cảm.
-
Ví dụ xấu:
{ "error": "SQL Syntax Error at line 23: SELECT * FROM users WHERE ..." }
-
Cách đúng:
{ "code": 500, "message": "Internal Server Error", "data": null }
=> Log đầy đủ lỗi nội bộ, nhưng chỉ trả về thông báo chung cho client.
8. Ghi log request
- Để debug API dễ dàng, cần log lại:
- URL request
- Tham số
- Headers
- Phương thức HTTP
- Response
- Thời gian xử lý
- Thêm
traceId
để liên kết các log của cùng một request -> dễ dàng tra cứu.
9. Đảm bảo tính idempotent
-
Nếu một request được gửi nhiều lần, API phải tránh xử lý trùng lặp.
-
Cách xử lý:
- Dùng
unique constraint
trong DB để ngăn insert trùng. - Dùng Redis để lưu
requestId
, nếu request trùng thì từ chối xử lý.
- Dùng
10. Giới hạn số bản ghi trong API batch
-
Batch API không nên cho phép gửi quá nhiều bản ghi một lúc -> dễ gây quá tải.
-
Giới hạn hợp lý:
- Mỗi request tối đa 500 bản ghi.
- Nếu gửi quá số này -> trả về lỗi.
11. Test tải trước khi triển khai
-
Ngay cả khi có rate limit, API vẫn cần stress test để kiểm tra khả năng chịu tải thực tế.
-
Dùng các công cụ như:
- JMeter
- Apache Bench (ab)
12. Xử lý bất đồng bộ
-
Những API xử lý lâu (VD: batch job) không nên chạy đồng bộ.
-
Giải pháp:
- Đẩy task vào message queue (Kafka, RabbitMQ).
- Trả về ngay response success.
- Để client check kết quả qua callback hoặc polling.
- Sử dụng WebSocket hoặc SocketIO
13. Ẩn dữ liệu nhạy cảm
-
Một số API response chứa dữ liệu cần che bớt, như:
- Số điện thoại ->
098****1234
- Số thẻ ngân hàng ->
5196****1234
- Số điện thoại ->
14. Tài liệu API đầy đủ
-
Một API tốt cần có tài liệu rõ ràng:
- URL
- Method (GET, POST...)
- Request params
- Response format
- Error codes
- Ví dụ request
-
Chuẩn hóa quy ước đặt tên
Để duy trì tính nhất quán:- Sử dụng
camelCase
cho tên trường. - Chuẩn hóa kiểu trường & độ dài (ví dụ: id là
Long
, status làint
). - Xác định định dạng thời gian thống nhất (ví dụ:
yyyy-MM-dd HH:mm:ss
). - Tài liệu cũng nên chỉ định cách sử dụng khóa
AK/SK
và tên miền API.
- Sử dụng
15. Chọn đúng phương thức HTTP
-
GET
: Đọc dữ liệu, không cần tham số body. -
POST
: Gửi dữ liệu, mở rộng dễ dàng. -
PUT
: Cập nhật dữ liệu. -
DELETE
: Xóa dữ liệu. -
Ưu tiên
POST
hơnGET
vì:GET
có giới hạn độ dài URL (~5000 ký tự).GET
dễ bị cache sai dữ liệu.
16. Dùng request headers đúng cách
- Các tham số quan trọng như
token
,traceId
nên để trong request header thay vì query string (trong body hay params). - Server có thể xử lý các thứ trên thông qua interceptor,tương tự với FE.
17. Thiết kế API theo nguyên tắc Single Responsibility
- Tránh API quá đa năng, chứa nhiều logic khác nhau.
- Chia nhỏ API theo use case cụ thể, dễ bảo trì hơn.
- Ví dụ: Thay vì thiết kế một API để xử lý mọi thứ, hãy tách chúng ra:
- API web:
/web/v1/order/create
/web/v1/order/fastCreate
- API mobile
/mobile/v1/order/create
/mobile/v1/order/fastCreate
-
Điều này tạo ra bốn API riêng biệt, mỗi API dành riêng cho một trường hợp sử dụng cụ thể.
-
Lợi ích:
- Logic kinh doanh vẫn rõ ràng.
- API dễ bảo trì hơn.
- Ít có nguy cơ xảy ra tác dụng phụ không mong muốn khi thực hiện thay đổi.
18. Batch Processing
-
API nên hỗ trợ batch processing thay vì xử lý từng record riêng lẻ.
-
Ví dụ sai:
/getOrder?id=1
→ Gọi 1,000 lần nếu cần 1,000 đơn hàng.
- Ví dụ đúng:
/getOrders?ids=[1,2,3,...]
→ Trả về một lần, tiết kiệm tài nguyên.
- Tương tự với insert/update/delete → Nên hỗ trợ batch để tối ưu hiệu suất.
Kết luận
Tuân thủ những best practice này sẽ giúp API an toàn, hiệu năng cao và dễ bảo trì. 💪🚀
All rights reserved