API Design phải biết dành cho website developer

0 0 0

Người đăng: Đỗ Tú

Theo Viblo Asia

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, timestampsecret key thành một chuỗi.
      • Tạo chữ ký (sign) bằng thuật toán hash như MD5.
      • Gửi chữ ký này trong request parameters hoặc headers.
    • Bên phía API gateway:
      • Lấy giá trị sign từ request.
      • Dùng cùng các tham số request, timestampsecret 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ệ.
  • 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ý.

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

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.

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ơn GET 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ì. 💪🚀

Bình luận

Bài viết tương tự

- vừa được xem lúc

Flutter - GetX - Using GetConnect to handle API request (Part 4)

Giới thiệu. Xin chào các bạn, lại là mình với series về GetX và Flutter.

0 0 361

- vừa được xem lúc

API vs WebSockets vs WebHooks: What to Choose?

. Khi xây dựng bất kì một ứng dụng nào, chúng ta đều cần phải có một cơ chế đáng tin cậy để giao tiếp giữa các thành phần của nó. Đây là khi APIs, WebSockets và WebHooks được ứng dụng vào.

0 0 103

- vừa được xem lúc

Sử dụng Fast JSON API serialization trong Ruby on Rails

Ở bài viết này chúng ta sẽ thử tạo 1 project API sử dụng gem fast_jsonapi cho serializer. Đầu tiên là tạo một project API mới. $ rails new rails-jsonapi --database=postgresql --skip-action-mailbox --skip-action-text --skip-spring -T --skip-turbolinks --api. .

0 0 136

- vừa được xem lúc

Test thử ba loại API chụp màn hình Windows

Hiện tại, Windows cung cấp khoảng ba cách để chụp màn hình. Thế thì cái nào là nhanh nhất? Tôi muốn test thử từng cái.

0 0 73

- vừa được xem lúc

Ngừng sử dụng REST cho API — GraphQL là cách tốt hơn

Mở đầu. REST đã được nhiều developers sử dụng để gửi dữ liệu qua HTTP trong khi GraphQL thường được trình bày như một công nghệ thay thế các API REST.

0 0 103

- vừa được xem lúc

Quản lý và sử dụng API trong Nuxt bằng cách sử dụng Repository Pattern

Mở đầu năm mới, à nhầm, mở đầu bài viết. Cái tên NuxtJS chắc hẳn cũng không còn xa lạ gì với những bạn yêu thích VueJS nữa, đương nhiên mình cũng là một chàng trai dành tình yêu to lớn cho frameworks này.

0 0 230