CORS là gì?

CORS (Cross-Origin Resource Sharing) là một cơ chế bảo mật trong trình duyệt web giúp kiểm soát việc chia sẻ tài nguyên giữa các nguồn gốc khác nhau. CORS cho phép hoặc từ chối các yêu cầu tài nguyên từ một nguồn gốc (origin) khác với nguồn gốc của trang web hiện tại, nhằm bảo vệ dữ liệu và ứng dụng khỏi các tấn công kẻ thù như Cross-Site Request Forgery (CSRF) và Cross-Site Scripting (XSS).

Nguồn Gốc (Origin) Là Gì?

Một nguồn gốc bao gồm ba phần:

  1. Giao thức (Protocol): HTTP hoặc HTTPS
  2. Tên miền (Domain): Ví dụ, example.com
  3. Cổng (Port): Ví dụ, cổng 80 cho HTTP và cổng 443 cho HTTPS

Hai URL khác nhau sẽ thuộc cùng một nguồn gốc nếu chúng có cùng giao thức, tên miền và cổng. Nếu bất kỳ phần nào của ba thành phần này khác nhau, đó sẽ là các nguồn gốc khác nhau.

CORS Hoạt Động Ra Sao?

Khi một trang web thực hiện một yêu cầu từ một nguồn gốc khác (cross-origin request), trình duyệt sẽ gửi yêu cầu đó với một số tiêu đề HTTP đặc biệt để kiểm tra xem yêu cầu có được phép hay không. Quá trình này có thể được chia thành hai loại yêu cầu: yêu cầu đơn giản (simple requests)yêu cầu phức tạp (complex requests).

Yêu Cầu Đơn Giản (Simple Requests)

Yêu cầu đơn giản là các yêu cầu HTTP mà không có bất kỳ tiêu đề đặc biệt nào hoặc không sử dụng các phương thức HTTP không phổ biến như PUT, DELETE. Để được coi là yêu cầu đơn giản, nó cần đáp ứng các điều kiện sau:

  • Phương thức HTTP là GET, POST hoặc HEAD.
  • Các tiêu đề HTTP không vượt quá một số giới hạn nhất định (chẳng hạn như Accept, Accept-Language, Content-Language, Content-Type với giá trị application/x-www-form-urlencoded, multipart/form-data, hoặc text/plain).

Khi trình duyệt gửi yêu cầu đơn giản, nó sẽ tự động thêm tiêu đề Origin vào yêu cầu. Máy chủ phản hồi yêu cầu với tiêu đề Access-Control-Allow-Origin để cho phép hoặc từ chối yêu cầu.

Ví dụ yêu cầu đơn giản:

Yêu cầu (Request):

GET /resource HTTP/1.1
Host: api.example.com
Origin: https://www.example.com

Phản hồi (Response):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.example.com

Yêu Cầu Phức Tạp (Complex Requests)

Nếu yêu cầu không phải là yêu cầu đơn giản, trình duyệt sẽ thực hiện một yêu cầu kiểm tra trước (preflight request) để xác minh tính hợp lệ của yêu cầu thực tế. Yêu cầu kiểm tra trước là một yêu cầu OPTIONS với tiêu đề Access-Control-Request-MethodAccess-Control-Request-Headers.

Yêu cầu kiểm tra trước (Preflight Request):

OPTIONS /resource HTTP/1.1
Host: api.example.com
Origin: https://www.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-Custom-Header

Phản hồi kiểm tra trước (Preflight Response):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-Custom-Header

Nếu yêu cầu kiểm tra trước thành công, trình duyệt sẽ gửi yêu cầu thực tế với các tiêu đề bổ sung, như Authorization.

Yêu cầu thực tế (Actual Request):

POST /resource HTTP/1.1
Host: api.example.com
Origin: https://www.example.com
Authorization: Bearer token
Content-Type: application/json

Phản hồi thực tế (Actual Response):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.example.com

Các Truy Vấn Dùng CORS

CORS có thể áp dụng cho nhiều loại truy vấn khác nhau, bao gồm nhưng không giới hạn ở:

  • Yêu cầu API: Khi một trang web frontend muốn lấy dữ liệu từ một API được lưu trữ trên một máy chủ khác.
  • Tải tài nguyên: Khi tải các tệp như hình ảnh, font chữ từ một nguồn gốc khác.
  • Chia sẻ dữ liệu: Khi các ứng dụng web muốn chia sẻ dữ liệu giữa các nguồn gốc khác nhau.

Hướng Dẫn Cài Đặt CORS

Dưới đây là hướng dẫn chi tiết về cách cấu hình CORS trên máy chủ sử dụng một số ngôn ngữ và công nghệ phổ biến:

1. Cấu Hình CORS Trên Máy Chủ Node.js Với Express

Sử dụng gói cors để dễ dàng cấu hình CORS:

npm install cors

Cấu hình CORS trong ứng dụng Express:

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

app.use(cors({
    origin: 'https://www.example.com', // Chỉ cho phép nguồn gốc này
    methods: 'GET,POST,PUT,DELETE',    // Các phương thức được phép
    allowedHeaders: 'Content-Type,Authorization' // Các tiêu đề được phép
}));

app.get('/resource', (req, res) => {
    res.json({ message: 'Hello World!' });
});

app.listen(3000, () => {
    console.log('Server running on port 3000');
});

2. Cấu Hình CORS Trong Máy Chủ PHP

Bạn có thể thêm tiêu đề CORS vào tệp PHP của bạn:

<?php
header("Access-Control-Allow-Origin: https://www.example.com");
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization");

echo json_encode(array('message' => 'Hello World!'));
?>

3. Cấu Hình CORS Trong Máy Chủ Apache

Sử dụng tệp .htaccess để cấu hình CORS:

<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "https://www.example.com"
    Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE"
    Header set Access-Control-Allow-Headers "Content-Type, Authorization"
</IfModule>

4. Cấu Hình CORS Trong Máy Chủ Nginx

Thêm cấu hình vào tệp cấu hình Nginx:

server {
    listen 80;
    server_name example.com;

    location / {
        add_header Access-Control-Allow-Origin https://www.example.com;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'Content-Type, Authorization';
    }
}

Ví Dụ Minh Họa

Giả sử bạn có một ứng dụng web được lưu trữ trên https://www.example.com và bạn muốn gửi yêu cầu đến API ở https://api.example.com. Để đảm bảo rằng yêu cầu được phép và dữ liệu được chia sẻ giữa hai nguồn gốc này, bạn cần cấu hình CORS đúng cách trên máy chủ API.

Bước 1: Cấu hình máy chủ API để cho phép yêu cầu từ https://www.example.com.

Bước 2: Trên máy chủ API, thêm các tiêu đề CORS cần thiết để cho phép các yêu cầu từ nguồn gốc cụ thể và các phương thức HTTP mong muốn.

Bước 3: Trên ứng dụng web, gửi yêu cầu từ frontend đến API và xử lý phản hồi dựa trên cấu hình CORS đã thiết lập.

Tóm Tắt

  • CORS (Cross-Origin Resource Sharing): Cơ chế bảo mật cho phép hoặc từ chối yêu cầu tài nguyên giữa các nguồn gốc khác nhau.
  • Hoạt Động: Sử dụng tiêu đề HTTP Origin, yêu cầu đơn giản và yêu cầu phức tạp (preflight requests).
  • Các Truy Vấn: CORS áp dụng cho API, tài nguyên, và chia sẻ dữ liệu giữa các nguồn gốc khác nhau.
  • Cấu Hình: Có thể cấu hình CORS trên các máy chủ Node.js, PHP, Apache, và Nginx bằng cách thiết lập các tiêu đề HTTP cần thiết.

Việc hiểu và cấu hình CORS chính xác giúp bảo mật ứng dụng web và đảm bảo rằng các yêu cầu tài nguyên từ các nguồn gốc khác nhau được xử lý một cách an toàn và chính xác.