Bảo mật API — 10 lớp API security — 10 layers

10 cơ chế · 4 tầng · 1 request đi xuyên qua tất cả 10 mechanisms, 4 tiers, one request passing through all of them

Bảo mật API không nằm ở một công tắc Securing an API isn't one setting

Mười cơ chế dưới đây không thay thế nhau và cũng không phải một danh sách phải làm đủ. Chúng nằm ở những chặng khác nhau trên đường đi của một request, và mỗi cái chỉ chặn đúng loại tấn công nó sinh ra để chặn. These ten don't substitute for each other, and they aren't a checklist to complete. They sit at different points along a request's path, and each one stops only the class of attack it was built for.

Lat cat bon tang phong thu / Section through the four defense tiers request từ Internet request from the internet Audit Logging Biên mạng Edge Rate Limiting IP Allowlisting CORS Policy ai được chạm tới, và bao nhiêu lần who may reach you, and how often Kênh truyền Channel mTLS Request Signing kết nối và nội dung có thật không is the connection and payload genuine Danh tính Identity API Keys OAuth 2.0 JWT Validation ai gọi, và được phép làm gì who is calling, what they may do Dữ liệu Data Input Sanitization dữ liệu có an toàn để xử lý không is this data safe to process logic nghiệp vụ business logic Nét đứt: mỗi tầng là một quyết định lúc chạy, không phải bức tường cố định. Dashed: each tier is a runtime decision, not a fixed wall.

Trước khi thêm bất cứ lớp nào Before you add any layer

Rất nhiều API không cần một cơ chế nào trong mười cái trên. Nếu bạn thoả cả bốn điều — chỉ phục vụ frontend của chính mình, đã chạy sau một gateway có sẵn, không xử lý tiền hay dữ liệu nhạy cảm, đội dưới mười người — hãy dừng ở đây. Plenty of APIs need none of the ten. If all four apply — you serve only your own frontend, you already run behind a managed gateway, you handle no money or sensitive data, and the team is under ten people — stop here.

Phương án rẻ nhất, khoảng một ngày công: The cheapest workable setup, about one day of work:
  1. HTTPS bắt buộc, HSTS bật, không còn cổng HTTP nào mở.HTTPS enforced, HSTS on, no HTTP port still listening.
  2. Session cookie của framework với HttpOnly; Secure; SameSite=Lax. Thu hồi phiên là một câu DELETE.Framework session cookies with HttpOnly; Secure; SameSite=Lax. Revoking a session is one DELETE.
  3. Giới hạn kích thước body và timeout ở tầng proxy.Body size limits and timeouts at the proxy.
  4. Rate limit mặc định của gateway ở mức thô, chưa cần tinh chỉnh.The gateway's default rate limit at a coarse setting, no tuning yet.
  5. Parameterized query ở mọi truy vấn. Đây là thứ duy nhất không được phép hoãn.Parameterized queries everywhere. The one item you never get to defer.
  6. Không ghi header Authorization và body request vào log.Never log Authorization headers or request bodies.

Dấu hiệu bạn đã vượt qua baseline Signs you've outgrown the baseline

Xuất hiện bên thứ ba tích hợp, nhiều tenant dùng chung hệ thống, tiền hoặc dữ liệu bị quản lý bởi quy định, hoặc lưu lượng lạ trong log mà bạn không giải thích được. Third parties start integrating, multiple tenants share the system, money or regulated data enters the picture, or traffic appears in the logs you can't explain.

Chọn lớp nào, trong 30 giây Picking a layer, in 30 seconds

Bắt đầu từ thứ bạn đang bảo vệ, không phải từ danh sách cơ chế. Start from what you're protecting, not from the list of mechanisms.

Mười cơ chế The ten mechanisms

Số hiệu giữ theo ảnh gốc để đối chiếu; thứ tự trình bày theo đường đi của request. Numbering follows the original image for reference; the order follows a request's path.

№01

Rate Limiting

Biên mạngEdge
 refill 10/s
     ↓
 [●●●●●●●●]  cap 100
     ↓
 token left   → 200
 bucket empty → 429 + Retry-After

Giới hạn số request một bên gọi được thực hiện trong một khoảng thời gian, tính theo IP, API key, user hoặc tenant. A cap on how many requests a caller may make in a window, counted per IP, API key, user, or tenant.

đánh đổithe trade Đổi việc thỉnh thoảng chặn nhầm người dùng hợp lệ lấy việc hệ thống không sập vì một client duy nhất. Trades the occasional false block of a legitimate user for the guarantee that no single client can take the system down.

Dùng choUse it for

  • Brute force ở màn hình đăng nhập, OTPBrute force on login and OTP
  • Endpoint đắt: tìm kiếm, xuất báo cáo, gọi LLMExpensive endpoints: search, exports, LLM calls
  • Cô lập tenant ồn ào trong SaaS dùng chungContaining a noisy tenant in shared SaaS

ĐượcYou gain

  • Hoá đơn hạ tầng có trần trên rõ ràngA hard ceiling on the infrastructure bill
  • Bán gói theo tầng không cần đổi codeTiered plans without touching app code
  • Chặn credential stuffing gần như miễn phíCredential stuffing blocked for almost nothing

MấtYou give up

  • Chặn nhầm người thật sau NAT và CGNATFalse blocks behind NAT and CGNAT
  • Botnet phân tán đi xuyên qua dễ dàngDistributed botnets walk straight through
  • Bộ đếm tập trung thành điểm chết đơn lẻThe central counter becomes a failure point

Dấu hiệu nhận biết.How to spot the need. Một client gọi 100 lần một phút thì hệ thống vẫn khoẻ, nhưng 10.000 lần một phút thì sập. One client at 100 requests per minute is fine; the same client at 10,000 takes the system down.

№09

IP Allowlisting

Biên mạngEdge
 203.0.113.0/24  → allow
 198.51.100.7    → allow
 everything else → drop at L3

 behind a CDN: trust only the hop
 your own proxy wrote into XFF

Chỉ chấp nhận kết nối từ những dải địa chỉ đã khai báo trước. Mọi thứ khác bị chặn ở tầng mạng, trước khi ứng dụng biết có ai gọi. Accepting connections only from address ranges declared in advance. Everything else is dropped before the application knows anyone called.

đánh đổithe trade Đổi tính linh hoạt và một danh sách phải chăm sóc suốt đời lấy bề mặt tấn công gần bằng không cho những đường vào cố định. Trades flexibility and a list you maintain forever for an attack surface near zero on fixed entry points.

Dùng choUse it for

  • Endpoint quản trị, chỉ mở cho VPN công tyAdmin endpoints, open to the corporate VPN only
  • Đối tác B2B có dải IP tĩnh trong hợp đồngB2B partners with contracted static ranges
  • Runner CI/CD được phép gọi endpoint deployCI/CD runners allowed to hit deploy endpoints

ĐượcYou gain

  • Rẻ nhất trong mười cơ chế, chặn ở tầng mạngThe cheapest of the ten, enforced at the network layer
  • Log sạch hẳn nhiễu từ máy quét tự độngLogs cleared of automated scanner noise
  • Dễ chứng minh hiệu lực với kiểm toánEasy to demonstrate to an auditor

MấtYou give up

  • IP không phải danh tính: bị chia sẻ, bị tái cấp phátAn IP is not an identity: shared, recycled
  • Danh sách mục nát sau vài thángThe list rots within months
  • Sai số hop thì X-Forwarded-For bị giảA wrong hop count lets X-Forwarded-For be spoofed

Dấu hiệu nhận biết.How to spot the need. Bạn viết ra giấy được toàn bộ nơi hợp lệ sẽ gọi API này, và danh sách đó đổi vài lần một năm chứ không phải vài lần một ngày. You can write down every legitimate caller on paper, and that list changes a few times a year rather than a few times a day.

№06

CORS Policy

Biên mạngEdge
 OPTIONS /orders
 Origin: https://app.example.com
   ↓
 Access-Control-Allow-Origin: <exact>
 Access-Control-Allow-Methods: GET, PUT
   ↓
 browser decides.
 curl ignores all of it.

Một cơ chế của trình duyệt để nới lỏng Same-Origin Policy. Nó cho phép, chứ không chặn — và nó bảo vệ trình duyệt của người dùng, không bảo vệ API của bạn. A browser mechanism for relaxing the Same-Origin Policy. It permits rather than blocks, and it protects your users' browsers, not your API.

đánh đổithe trade Đổi phạm vi tấn công trong trình duyệt của chính người dùng lấy sự tiện lợi khi tích hợp frontend. Trades attack surface inside your own users' browsers for frontend integration convenience.

Dùng choUse it for

  • SPA ở domain khác gọi APIAn SPA on another domain calling the API
  • API công khai cho JavaScript bên thứ baPublic APIs read by third-party JavaScript
  • Widget nhúng vào website khách hàngWidgets embedded in customer sites

ĐượcYou gain

  • Tách frontend và backend mà vẫn giữ SOPSplit frontend and backend, SOP intact
  • Preflight chặn method và header lạ sớmPreflight rejects odd methods and headers early
  • Kiểm soát chính xác origin nào được gửi cookiePrecise control over which origins may send cookies

MấtYou give up

  • Vô hiệu với client không phải trình duyệtUseless against non-browser clients
  • Echo nguyên Origin mở cửa cho mọi websiteReflecting Origin opens the door to every site
  • Không thay thế được chống CSRFIt is not CSRF protection

Dấu hiệu nhận biết.How to spot it. Lỗi chỉ xuất hiện trong trình duyệt, còn curl và Postman vẫn chạy ngon lành. The failure appears only in a browser while curl and Postman work fine.

№07

mTLS

Kênh truyềnChannel
 client               server
   |-- ClientHello ----→ |
   | ←- cert + request --|
   |-- client cert -----→|
   |-- sign w/ priv key →|
   |===== verified ======|

 rejected here = never a request

TLS hai chiều: client cũng trình chứng thư và chứng minh mình giữ khoá riêng. Danh tính được xác lập trước byte HTTP đầu tiên. Two-way TLS: the client presents a certificate too and proves it holds the private key. Identity is settled before the first HTTP byte.

đánh đổithe trade Đổi một hệ thống PKI phải nuôi suốt vòng đời sản phẩm lấy việc xoá bỏ hoàn toàn khái niệm bí mật dùng chung có thể bị rò. Trades a PKI you operate for the product's whole lifetime for the complete elimination of shared secrets that can leak.

Dùng choUse it for

  • Service-to-service trong service meshService-to-service inside a mesh
  • Tích hợp ngân hàng, thanh toán, y tếBanking, payments, healthcare integrations
  • Thiết bị IoT nạp chứng thư từ nhà máyIoT devices provisioned at manufacture

ĐượcYou gain

  • Không có bí mật dùng chung nào để ròNo shared secret left to leak
  • Từ chối ngay ở handshake, ứng dụng không bị chạmRejection at the handshake, the app is never touched
  • Khoá riêng nằm trong HSM, không xuất ra đượcPrivate keys in an HSM, non-exportable

MấtYou give up

  • Vận hành PKI là gánh nặng thật và lâu dàiRunning a PKI is real, permanent work
  • Chứng thư hết hạn vào lúc không ai trựcCertificates expire when nobody is on call
  • Không dùng được cho trình duyệt người dùng phổ thôngUnusable for consumer browsers

Dấu hiệu nhận biết.How to spot the fit. Cả hai đầu do bạn hoặc một đối tác cố định vận hành, và bạn kiểm soát được việc phát hành chứng thư. Both ends are run by you or a fixed partner, and you control certificate issuance.

№08

Request Signing

Kênh truyềnChannel
 canonical = METHOD \n PATH \n
             host \n ts \n nonce \n
             sha256(body)

 sig = HMAC-SHA256(secret, canonical)
 X-Signature / X-Timestamp / X-Nonce

 the secret itself never travels

Client ký một chuỗi chuẩn hoá dựng từ chính request; server dựng lại đúng chuỗi ấy và so chữ ký. Sai một byte trong body là lộ ngay. The client signs a canonical string built from the request itself; the server rebuilds it and compares. One changed byte in the body and it shows.

đánh đổithe trade Đổi độ phức tạp cho cả hai phía và chi phí hỗ trợ tích hợp lấy sự đảm bảo rằng nội dung request không bị ai sửa dọc đường. Trades complexity on both sides and a real support cost for the guarantee that nobody altered the request along the way.

Dùng choUse it for

  • Webhook: chứng minh payload đến từ đúng nguồnWebhooks: proving the payload's true sender
  • API tài chính: chuyển tiền, đặt lệnhFinancial APIs: transfers, orders
  • Client di động không đáng tin, chống sửa tham sốUntrusted mobile clients, stopping tampering

ĐượcYou gain

  • Toàn vẹn đầu cuối qua mọi proxy và CDNEnd-to-end integrity across every proxy and CDN
  • Timestamp và nonce chặn replayTimestamp and nonce defeat replay
  • Khoá bí mật không bao giờ đi qua đường truyềnThe secret never travels the wire

MấtYou give up

  • Chuẩn hoá chuỗi ký lệch nhau là hỏng, khó debugCanonicalization mismatches, painful to debug
  • Lệch đồng hồ tạo ra lỗi giảClock drift produces false rejections
  • Lưu nonce thêm trạng thái vào thiết kế statelessStored nonces add state to a stateless design

Dấu hiệu nhận biết.How to spot the need. Việc sửa một request vốn hợp lệ — đổi số tiền, đổi tài khoản đích — gây thiệt hại thật. Modifying an otherwise valid request — changing an amount or a destination account — causes real harm.

№02

API Keys

Danh tínhIdentity
 key = <type>_<env>_<random secret>
       sk_    live_  7f2a9c4e...

 client → header: X-API-Key
 server → sha256 lookup → app, scope
 stored as a hash, never plaintext

Một chuỗi bí mật tĩnh định danh ứng dụng đang gọi, không phải người dùng cuối. Ai cầm được thì dùng được. A static secret identifying the calling application, not an end user. Whoever holds it can use it.

đánh đổithe trade Đổi khả năng phân quyền theo người dùng, và chấp nhận rủi ro của một bí mật tĩnh, lấy việc tích hợp gần như tức thì. Trades per-user authorization and accepts the risk of a static secret in exchange for near-instant integration.

Dùng choUse it for

  • Giao tiếp server-to-server nội bộInternal server-to-server traffic
  • API công khai trả dữ liệu không nhạy cảmPublic APIs serving non-sensitive data
  • Đo lường và tính phí theo lượt gọiUsage metering and per-call billing

ĐượcYou gain

  • Triển khai trong vài giờ, không cần tài liệu dàiShippable in hours, no documentation needed
  • Thu hồi và xoay vòng từng client độc lậpRevoked and rotated per client
  • Không gọi về authorization server, không thêm độ trễNo authorization server round trip, no added latency

MấtYou give up

  • Bí mật tĩnh không tự hết hạn, rò là dùng được mãiA static secret never expires on its own
  • Rò rỉ rất dễ: Git, log, bundle app, query stringLeaks easily: Git, logs, app bundles, query strings
  • Không mang ngữ cảnh người dùng, không phân quyền chi tiếtNo user context, so no fine-grained permissions

Dấu hiệu nhận biết.How to spot the fit. Chủ thể gọi API là một chương trình chứ không phải một con người, và bạn chỉ cần biết "app nào". The caller is a program rather than a person, and all you need to know is which app.

№03

OAuth 2.0

Danh tínhIdentity
 user → app → authz server
                ↓ consent
        code + PKCE verifier
                ↓
        access token (≤ 15 min)
                ↓
 app → API: Authorization: Bearer ...

 the password never touches the app

Một framework uỷ quyền: ứng dụng truy cập tài nguyên thay mặt chủ sở hữu mà không cần biết mật khẩu. Phần xác thực nằm ở OpenID Connect, tầng xây trên nó. An authorization framework: an app reaches resources on the owner's behalf without ever seeing their password. Authentication belongs to OpenID Connect, the layer above.

đánh đổithe trade Đổi độ phức tạp vận hành và một thành phần hạ tầng phải luôn sống lấy khả năng uỷ quyền có phạm vi và thu hồi được mà không phát tán mật khẩu. Trades operational complexity and one more component that must stay up for scoped, revocable delegation without spreading passwords around.

Dùng choUse it for

  • "Đăng nhập bằng Google" trong ứng dụng của bạn"Sign in with Google" inside your app
  • Mở API cho nhà phát triển bên thứ baOpening an API to third-party developers
  • Microservice gọi nhau qua client credentialsMicroservices calling each other via client credentials

ĐượcYou gain

  • Mật khẩu không đi qua tay ứng dụng bên thứ baPasswords never pass through third-party apps
  • Token ngắn hạn thu hẹp thiệt hại còn vài phútShort-lived tokens cut the blast radius to minutes
  • Thu hồi tập trung, scope giới hạn rõ ràngCentral revocation and explicit scopes

MấtYou give up

  • Phức tạp, và phần lớn nằm ở chỗ dễ làm saiComplexity, most of it where mistakes are easy
  • Authorization server thành điểm chết đơn lẻThe authorization server is a single point of failure
  • Quá nặng cho API nội bộ giữa hai service cùng độiToo heavy for internal APIs run by one team

Dấu hiệu nhận biết.How to spot the fit. Người dùng cần cho phép một ứng dụng khác chạm vào dữ liệu của họ mà không đưa mật khẩu. A user needs to let another application touch their data without handing over a password.

№04

JWT Validation

Danh tínhIdentity
 header  .  payload           .  signature
 alg,kid    sub,iss,aud,exp      over both

 signed, NOT encrypted

 check: alg pinned → sig via kid
        → exp → iss → aud → scope

Token tự chứa, ký bởi bên phát hành, nên mọi service có khoá công khai đều tự xác minh được. Từ quan trọng ở đây là validation, không phải JWT. A self-contained token signed by its issuer, so any service with the public key can verify it alone. The important word here is validation, not JWT.

đánh đổithe trade Đổi khả năng thu hồi tức thì lấy việc xác thực không cần tra cứu tập trung. Trades instant revocation for authentication that needs no central lookup.

Dùng choUse it for

  • Xác thực không trạng thái giữa microserviceStateless auth across microservices
  • Gateway xác minh một lần rồi gắn claim đi tiếpA gateway verifying once, then passing claims on
  • Phiên đăng nhập trên di độngMobile sessions

ĐượcYou gain

  • Xác minh cục bộ, không phụ thuộc databaseLocal verification, no database dependency
  • Mở rộng ngang không cần trạng thái dùng chungHorizontal scale with no shared state
  • Claim mang sẵn vai trò, tenant, scopeClaims carry roles, tenant, and scopes

MấtYou give up

  • Không thu hồi được trước khi hết hạnNo revocation before expiry
  • Payload chỉ ký, ai chặn được cũng đọc đượcThe payload is signed, not encrypted
  • Bỏ qua aud là token của API khác dùng được ở đâySkip aud and another API's tokens work here

Dấu hiệu nhận biết.How to spot the fit. Mỗi service cần tự xác minh danh tính mà không gọi về một auth service trung tâm. Each service must verify identity for itself without calling a central auth service.

№05

Input Sanitization

Dữ liệuData
 in  → schema allowlist → 400 if bad
 use → logic runs on clean data
 out → SQL   : parameterized query
       HTML  : entity encode
       shell : argv, never a string

Việc cần làm thật sự gồm hai phần: từ chối dữ liệu sai hình dạng ngay tại biên, và mã hoá đúng ngữ cảnh tại nơi dữ liệu được dùng. Cắt gọt ký tự xấu là phương án yếu nhất. The real work has two parts: rejecting badly shaped data at the boundary, and encoding for context at the point of use. Stripping bad characters is the weakest option.

đánh đổithe trade Đổi một phần linh hoạt của API và công sức bảo trì schema lấy việc loại bỏ hẳn một họ lỗ hổng. Trades some API flexibility and the upkeep of a schema for the removal of an entire vulnerability family.

Dùng choUse it for

  • Mọi API nhận dữ liệu từ ngoài, không ngoại lệEvery API taking outside data, no exceptions
  • Upload file: kiểm magic byte, không tin đuôi tênUploads: check magic bytes, not the extension
  • URL người dùng nhập mà server sẽ gọi tớiUser-supplied URLs your server will fetch

ĐượcYou gain

  • Loại bỏ họ lỗ hổng injectionThe injection family, removed
  • Schema trở thành tài liệu API luôn đúngA schema that doubles as always-correct docs
  • Ít crash hơn vì dữ liệu dị dạngFewer crashes from malformed data

MấtYou give up

  • Blocklist luôn thua trước một cách mã hoá mớiBlocklists always lose to a new encoding
  • Validator quá chặt chặn nhầm dữ liệu hợp lệOver-strict validators reject valid data
  • Payload lồng nhau nhiều tầng khó phủ hếtDeeply nested payloads are hard to cover

Dấu hiệu nhận biết.How to spot the risk. Một chuỗi do người ngoài nhập vào rồi được diễn giải bởi SQL, HTML, shell, XML hoặc template engine. An outsider-supplied string later interpreted by SQL, HTML, a shell, XML, or a template engine.

№10

Audit Logging

Dữ liệuData
 {ts, actor, action, target,
  source_ip, trace_id, result}

 → append-only store, no delete right
 → redacted inside the logger

 not in here: tokens, PII, card data

Bản ghi chỉ thêm, trả lời được ai làm gì với cái gì, lúc nào, từ đâu, kết quả ra sao. Application log để gỡ lỗi; audit log để điều tra và chứng minh. An append-only record answering who did what to which object, when, from where, with what result. Application logs are for debugging; audit logs are for investigation and proof.

đánh đổithe trade Đổi chi phí lưu trữ và kỷ luật xử lý dữ liệu nhạy cảm lấy khả năng biết chính xác chuyện gì đã xảy ra sau khi mọi thứ đã đổ vỡ. Trades storage cost and the discipline of handling sensitive data for knowing exactly what happened once everything has gone wrong.

Dùng choUse it for

  • Điều tra sự cố, dựng lại chuỗi hành độngIncident investigation, reconstructing a sequence
  • Tuân thủ SOC 2, ISO 27001, PCI DSS, GDPRSOC 2, ISO 27001, PCI DSS, GDPR compliance
  • Hỗ trợ khách hàng: ai đã xoá bản ghi nàySupport: who deleted this record

ĐượcYou gain

  • Điều tra rút từ nhiều ngày xuống vài phútInvestigations cut from days to minutes
  • Lớp duy nhất còn giá trị sau khi các lớp khác thủngThe only layer with value after the others fail
  • Điều kiện bắt buộc để qua kiểm toánA prerequisite for passing audits

MấtYou give up

  • Phát hiện chứ không ngăn chặn; không ai đọc thì bằng khôngIt detects, it doesn't prevent
  • Dễ ghi nhầm token và dữ liệu cá nhân vào logEasy to capture tokens and personal data by accident
  • Chi phí ingest và lưu trữ tăng theo lưu lượngIngest and storage costs scale with traffic

Dấu hiệu nhận biết.How to spot the gap. Bạn không trả lời được "tài khoản nào đã đổi cấu hình này lúc ba giờ sáng thứ Bảy tuần trước". You can't answer "which account changed this setting at 3 a.m. last Saturday".

Bảng đánh đổi The trade-off table

Đọc cột "vận hành" trước. Chi phí thật của một lớp bảo mật nằm ở ngày thứ 400, không phải ngày đầu. Read the "ongoing" column first. The real cost of a layer shows up on day 400, not day one.

Cơ chếMechanism Chống chủ yếuMainly stops Ngăn / Phát hiệnPrevent / Detect Ban đầuSetup Vận hànhOngoing
Rate Limiting Lạm dụng, brute forceAbuse, brute force NgănPrevent ●○○●●○
IP Allowlisting Truy cập từ nơi không mong muốnAccess from unexpected places NgănPrevent ●○○●●●
CORS Policy Site lạ đọc dữ liệu trong trình duyệtHostile sites reading data in-browser Ngăn, chỉ trong trình duyệtPrevent, browser only ●○○●○○
mTLS Client giả mạo, MITMForged clients, MITM NgănPrevent ●●●●●●
Request Signing Sửa nội dung, replayTampering, replay NgănPrevent ●●●●●○
API Keys Bên gọi ẩn danhAnonymous callers NgănPrevent ●○○●●○
OAuth 2.0 Phát tán mật khẩu, quyền quá rộngPassword sharing, over-broad access NgănPrevent ●●●●●●
JWT Validation Token giả, mạo danhForged tokens, impersonation NgănPrevent ●●○●○○
Input Sanitization Injection mọi loạiInjection of every kind NgănPrevent ●●○●●○
Audit Logging Không truy được trách nhiệmLack of accountability Phát hiệnDetect ●●○●●●

Sai lầm thường gặp Anti-patterns

Ba câu cần nhớ Three things to remember