CORS: "Cảnh Sát Biên Giới" Cho API Node.js Của Bạn!
Nodejs

CORS: "Cảnh Sát Biên Giới" Cho API Node.js Của Bạn!

Author

Admin System

@root

Ngày xuất bản

23 Mar, 2026

Lượt xem

4 Lượt

"cors package"

Bắt Tay CORS: "Cảnh Sát Biên Giới" Cho API Node.js Của Bạn!

Chào các chiến thần Gen Z! Hôm nay, thầy Creyt sẽ giải mã một trong những nỗi ám ảnh kinh hoàng nhất của dân dev frontend khi "bắt tay" với backend: lỗi CORS. Nghe tên đã thấy "khoai" rồi đúng không? Đừng lo, với package cors trong Node.js, chúng ta sẽ biến nỗi sợ hãi này thành món khai vị!

1. CORS là cái quái gì và để làm gì?

Để dễ hình dung, các bạn cứ tưởng tượng thế này:

Bạn là chủ một quán bar cực kỳ xịn xò (chính là cái API backend Node.js của bạn đấy). Khách hàng (là cái ứng dụng frontend bạn đang code, chạy trên React, Angular, Vue, hay thậm chí là một trang HTML đơn giản) muốn vào bar của bạn để gọi đồ (gửi request lấy dữ liệu).

Nhưng mà, quán bar của bạn lại có một "cảnh sát biên giới" cực kỳ nghiêm ngặt (tên nó là Same-Origin Policy - SOP, chính sách bảo mật của trình duyệt). Ông cảnh sát này chỉ cho phép những vị khách đến từ "cùng một khu phố" (cùng một origin - tức là cùng giao thức, domain và port) vào bar thôi. Ví dụ, nếu website của bạn chạy ở https://app.example.com, thì nó chỉ được phép gọi API từ https://api.example.com hoặc https://app.example.com/api thôi.

Nếu có một vị khách từ "khu phố khác" (ví dụ, frontend của bạn đang chạy ở http://localhost:3000 mà muốn gọi API ở http://localhost:5000, hoặc một website evil.com muốn gọi API của bạn) mà không có "giấy phép đặc biệt" thì sao? Ông cảnh sát sẽ "gào thét" lên một cái lỗi quen thuộc: "CORS Error!" và không cho vị khách đó vào.

Vậy, CORS (Cross-Origin Resource Sharing) chính là cái "giấy phép đặc biệt" mà quán bar của bạn (server) cấp cho những vị khách "ngoại quốc" đó. Nó là một cơ chế bảo mật cho phép server kiểm soát xem những "khu phố" nào được phép truy cập tài nguyên của mình. Mục đích là để ngăn chặn các website độc hại truy cập dữ liệu của bạn mà không được phép.

Package cors trong Node.js (thường dùng với Express.js) chính là "ông chủ quán bar" có kinh nghiệm, giúp bạn dễ dàng quản lý và cấp những "giấy phép" này một cách gọn gàng, an toàn, không cần phải tự mình viết luật lệ phức tạp.

2. Code Ví Dụ Minh Họa: Mở Cửa Quán Bar Một Cách Thông Minh

Đầu tiên, bạn cần cài đặt corsexpress:

npm install cors express

Giờ thì xem cách chúng ta "thuần hóa" nó:

Ví dụ 1: Mở cửa cho tất cả (chỉ dùng khi dev thôi nhé!)

Đây là cách nhanh nhất để "tắt" lỗi CORS khi đang phát triển. Giống như bạn mở toang cửa quán bar, ai vào cũng được. Thầy Creyt nhắc lại: CHỈ DÙNG KHI DEV THÔI!

const express = require('express');
const cors = require('cors');
const app = express();

// Sử dụng cors middleware
// Điều này cho phép MỌI origin truy cập API của bạn.
// CỰC KỲ KHÔNG AN TOÀN TRONG PRODUCTION!
app.use(cors());

// Một route ví dụ
app.get('/data', (req, res) => {
  res.json({ message: 'Đây là dữ liệu từ server của bạn!' });
});

const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
  console.log(`Server đang chạy trên cổng ${PORT}`);
});

Ví dụ 2: Mở cửa có chọn lọc (Cách dùng chuẩn chỉ)

Đây là cách mà thầy Creyt khuyên dùng trong hầu hết các trường hợp, đặc biệt là khi đưa lên production. Bạn chỉ cho phép những "khu phố" (origins) cụ thể vào bar của bạn thôi.

const express = require('express');
const cors = require('cors');
const app = express();

// Cấu hình CORS để chỉ cho phép các origin cụ thể
const corsOptions = {
  origin: ['http://localhost:3000', 'https://your-frontend-app.com'], // Danh sách các origin được phép
  methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', // Các HTTP methods được phép
  credentials: true, // Cho phép gửi cookies, authorization headers, v.v.
  optionsSuccessStatus: 204 // Một số trình duyệt cũ hơn có thể cần status này
};

// Áp dụng cấu hình CORS
app.use(cors(corsOptions));

// Một route ví dụ
app.get('/secure-data', (req, res) => {
  // Giả sử bạn có middleware xác thực ở đây
  res.json({ message: 'Đây là dữ liệu bảo mật từ server!' });
});

const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
  console.log(`Server đang chạy trên cổng ${PORT}`);
});

Giải thích chi tiết các corsOptions:

  • origin: Quan trọng nhất! Đây là danh sách các domain (hoặc một domain duy nhất dưới dạng string) mà bạn cho phép truy cập API. Nếu request đến từ một origin không có trong danh sách, nó sẽ bị chặn.
  • methods: Các HTTP method (GET, POST, PUT, DELETE,...) mà các origin được phép sử dụng. Mặc định, cors cho phép tất cả các method tiêu chuẩn.
  • credentials: Khi true, cho phép trình duyệt gửi cookie, HTTP authentication headers (ví dụ: Authorization) cùng với cross-origin request. Lưu ý: Nếu bạn đặt credentials: true, bạn không thể dùng origin: '*'. Phải chỉ định origin cụ thể!
  • allowedHeaders: Các HTTP header mà client được phép gửi trong request cross-origin. Mặc định, một số header cơ bản đã được cho phép.
  • exposedHeaders: Các HTTP header mà client được phép đọc từ response cross-origin (mặc định trình duyệt chỉ cho phép đọc một số header cơ bản).
Illustration

3. Mẹo (Best Practices) để ghi nhớ và dùng thực tế

Thầy Creyt có vài chiêu để các bạn "ăn điểm" với CORS:

  • Đừng bao giờ app.use(cors()) trong production! (Trừ khi bạn là một hacker có đạo đức và đang thử nghiệm). Nó như mở toang cửa cho mọi người, kể cả trộm cướp vào nhà bạn. Hậu quả là dữ liệu của bạn có thể bị đánh cắp hoặc bị lợi dụng.
  • Luôn chỉ định origin rõ ràng và cụ thể. Đây là "kim chỉ nam" để bảo vệ API của bạn. Chỉ cấp "giấy phép" cho những ai bạn tin tưởng.
  • Hiểu về credentials: true: Dùng cái này khi bạn cần gửi cookie hoặc authorization token qua các request cross-origin (ví dụ, để duy trì trạng thái đăng nhập). Nhớ là khi bật credentials, origin bắt buộc phải là một domain cụ thể, không được dùng *.
  • Preflight requests (OPTIONS): Khi client gửi một request "phức tạp" (ví dụ: dùng method khác GET/POST đơn giản, hoặc có custom header), trình duyệt sẽ tự động gửi một request OPTIONS trước (gọi là "preflight request") để hỏi server xem request chính có được phép hay không. Package cors tự động xử lý các preflight request này cho bạn, bạn không cần phải làm gì thêm.
  • Thứ tự Middleware: Luôn đặt app.use(cors(corsOptions)) trước các route xử lý request của bạn. Nếu không, request có thể bị chặn bởi các route khác trước khi cors kịp xử lý.

4. Ví dụ thực tế các ứng dụng/website đã ứng dụng

CORS không phải là thứ gì đó xa vời, nó hiện diện ở khắp mọi nơi bạn thấy frontend và backend "tách đôi":

  • Các ứng dụng SPA (Single Page Applications): Hầu hết các ứng dụng React, Angular, Vue.js hiện đại đều chạy trên một domain riêng (ví dụ: app.yourcompany.com) và gọi API từ một domain khác (ví dụ: api.yourcompany.com). CORS là bắt buộc để chúng có thể giao tiếp được.
  • Mobile Apps: Khi ứng dụng di động của bạn (iOS/Android) gọi đến một backend API, về lý thuyết thì không bị CORS vì mobile app không phải là trình duyệt. Tuy nhiên, khi bạn phát triển một Admin Panel hoặc Web Portal cho mobile app đó, bạn lại quay về câu chuyện CORS.
  • Microservices: Nếu bạn có nhiều dịch vụ nhỏ giao tiếp với nhau, và một trong số chúng là một "cổng" (Gateway) mà frontend web gọi đến, thì CORS sẽ phát huy tác dụng ở đó.
  • Ví dụ cụ thể: Bạn đang code một ứng dụng thương mại điện tử. Frontend của bạn chạy trên localhost:3000 (khi dev) hoặc shop.mycompany.com (khi deploy). Backend API của bạn chạy trên localhost:5000 (khi dev) hoặc api.mycompany.com (khi deploy). Khi frontend cố gắng fetch('/products') từ backend, nếu không có CORS, trình duyệt sẽ chặn đứng và báo lỗi.

5. Thử nghiệm và Hướng dẫn nên dùng cho case nào

  • Trong môi trường Development (dev):

    • Bạn có thể dùng app.use(cors()) một cách an toàn để "tắt" lỗi CORS và tập trung vào việc phát triển tính năng. Đừng quên thay đổi nó khi deploy nhé!
    • Hoặc tốt hơn, dùng cors({ origin: 'http://localhost:3000' }) nếu frontend của bạn chạy trên cổng 3000.
  • Trong môi trường Production (prod):

    • BẮT BUỘC phải chỉ định origin cụ thể. Ví dụ: cors({ origin: 'https://your-frontend-app.com' }) hoặc một mảng các domain nếu bạn có nhiều frontend.
    • Nếu bạn có nhiều subdomain, có thể dùng regex (nhưng cẩn thận).
  • API công khai (Public API):

    • Nếu bạn đang xây dựng một API mà bất kỳ ai cũng có thể sử dụng (ví dụ: API thời tiết, API dữ liệu công cộng), bạn có thể cân nhắc mở rộng origin hơn, thậm chí là * (nhưng vẫn nên cân nhắc kỹ về bảo mật, đặc biệt nếu có dữ liệu nhạy cảm). Thường thì các Public API sẽ yêu cầu API Key thay vì dựa vào CORS để bảo mật.
  • API nội bộ/Microservices không qua trình duyệt:

    • Nếu các dịch vụ backend của bạn giao tiếp với nhau mà không có trình duyệt nào liên quan, bạn không cần quan tâm đến CORS. CORS là một cơ chế bảo mật của trình duyệt, không phải của server.

Nhớ nhé các bạn, CORS không phải là kẻ thù, nó là một "vệ sĩ" mà chúng ta cần biết cách điều khiển. Hiểu rõ và sử dụng đúng cors package sẽ giúp API của bạn vừa mạnh mẽ, vừa an toàn, và quan trọng nhất là không còn gây "đau đầu" cho frontend nữa! Cứ thế mà triển thôi!

Thuộc Series: Nodejs

Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

#tech #cyberpunk #laravel
Chỉnh sửa bài viết

Bình luận (0)

Vui lòng Đăng Nhập để Bình luận

Hỗ trợ Markdown cơ bản
Nguyễn Văn A
1 ngày trước

Tính năng này đỉnh quá ad ơi, chờ mãi mới thấy một blog Tiếng Việt có UI/UX xịn như vầy!