Tiếng Việt

Khám phá bí mật của CORS (Chia sẻ Tài nguyên Liên nguồn gốc) và học cách kích hoạt các yêu cầu liên miền một cách an toàn trong ứng dụng web của bạn. Hướng dẫn toàn diện này bao gồm mọi thứ từ cơ bản đến cấu hình nâng cao, đảm bảo giao tiếp liền mạch và an toàn giữa các nguồn gốc khác nhau.

Giải mã CORS: Hướng dẫn Toàn diện về Chia sẻ Tài nguyên Liên nguồn gốc

Trong thế giới web kết nối ngày nay, các ứng dụng thường xuyên cần truy cập tài nguyên từ các nguồn gốc khác nhau. Đây là lúc Chia sẻ Tài nguyên Liên nguồn gốc (CORS) phát huy tác dụng. CORS là một cơ chế bảo mật quan trọng chi phối cách các trình duyệt web xử lý các yêu cầu từ một nguồn gốc (miền, giao thức và cổng) đến một nguồn gốc khác. Hiểu về CORS là điều cần thiết đối với mọi nhà phát triển web để xây dựng các ứng dụng web an toàn và hoạt động tốt.

Chính sách Cùng Nguồn gốc (Same-Origin Policy) là gì?

Trước khi đi sâu vào CORS, điều quan trọng là phải hiểu về Chính sách Cùng Nguồn gốc (SOP). SOP là một cơ chế bảo mật cơ bản được triển khai trong các trình duyệt web. Mục đích của nó là ngăn chặn các tập lệnh độc hại trên một trang web truy cập dữ liệu nhạy cảm trên một trang web khác. Một nguồn gốc được xác định bởi sự kết hợp của giao thức (ví dụ: HTTP hoặc HTTPS), miền (ví dụ: example.com) và số cổng (ví dụ: 80 hoặc 443). Hai URL được coi là có cùng nguồn gốc nếu chúng chia sẻ cùng giao thức, miền và cổng.

Ví dụ:

SOP hạn chế các tập lệnh truy cập tài nguyên từ một nguồn gốc khác trừ khi có các biện pháp cụ thể, chẳng hạn như CORS, để cho phép điều đó.

Tại sao CORS lại cần thiết?

Mặc dù Chính sách Cùng Nguồn gốc rất quan trọng đối với bảo mật, nó cũng có thể gây hạn chế. Nhiều ứng dụng web hiện đại dựa vào việc tìm nạp dữ liệu từ các máy chủ khác nhau, chẳng hạn như API hoặc mạng phân phối nội dung (CDN). CORS cung cấp một cách có kiểm soát để nới lỏng SOP và cho phép các yêu cầu liên nguồn gốc hợp pháp trong khi vẫn duy trì bảo mật.

Hãy xem xét một kịch bản trong đó một ứng dụng web được lưu trữ trên http://example.com cần tìm nạp dữ liệu từ một máy chủ API được lưu trữ trên http://api.example.net. Nếu không có CORS, trình duyệt sẽ chặn yêu cầu này do SOP. CORS cho phép máy chủ API chỉ định rõ ràng nguồn gốc nào được phép truy cập tài nguyên của nó, giúp ứng dụng web hoạt động chính xác.

Cách CORS hoạt động: Những điều cơ bản

CORS hoạt động thông qua một chuỗi các header HTTP được trao đổi giữa máy khách (trình duyệt) và máy chủ. Máy chủ sử dụng các header này để thông báo cho trình duyệt biết liệu nó có được phép truy cập tài nguyên được yêu cầu hay không. Header HTTP quan trọng liên quan là Access-Control-Allow-Origin.

Kịch bản 1: Yêu cầu Đơn giản (Simple Request)

Một "yêu cầu đơn giản" là một yêu cầu GET, HEAD hoặc POST đáp ứng các tiêu chí cụ thể (ví dụ: header Content-Type là một trong các giá trị application/x-www-form-urlencoded, multipart/form-data, hoặc text/plain). Trong trường hợp này, trình duyệt gửi yêu cầu trực tiếp đến máy chủ và máy chủ phản hồi bằng header Access-Control-Allow-Origin.

Yêu cầu từ Client (từ http://example.com):

GET /data HTTP/1.1
Host: api.example.net
Origin: http://example.com

Phản hồi từ Server (từ http://api.example.net):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json

{
  "data": "Một số dữ liệu từ máy chủ"
}

Trong ví dụ này, máy chủ phản hồi với Access-Control-Allow-Origin: http://example.com, cho biết rằng các yêu cầu từ http://example.com được cho phép. Nếu nguồn gốc trong yêu cầu không khớp với giá trị trong header Access-Control-Allow-Origin (hoặc nếu header không có), trình duyệt sẽ chặn phản hồi và ngăn tập lệnh phía máy khách truy cập dữ liệu.

Kịch bản 2: Yêu cầu Preflight (cho các Yêu cầu Phức tạp)

Đối với các yêu cầu phức tạp hơn, chẳng hạn như những yêu cầu sử dụng các phương thức HTTP như PUT, DELETE hoặc những yêu cầu có các header tùy chỉnh, trình duyệt sẽ thực hiện một yêu cầu "preflight" bằng phương thức HTTP OPTIONS. Yêu cầu preflight này hỏi xin phép máy chủ trước khi gửi yêu cầu thực tế. Máy chủ phản hồi bằng các header chỉ định các phương thức, header và nguồn gốc nào được cho phép.

Yêu cầu Preflight từ Client (từ http://example.com):

OPTIONS /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header

Phản hồi từ Server (từ http://api.example.net):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET, PUT, DELETE
Access-Control-Allow-Headers: X-Custom-Header, Content-Type
Access-Control-Max-Age: 3600

Giải thích các Header:

Nếu phản hồi preflight của máy chủ cho thấy yêu cầu được cho phép, trình duyệt sẽ tiến hành với yêu cầu thực tế. Ngược lại, trình duyệt sẽ chặn yêu cầu.

Yêu cầu thực tế từ Client (từ http://example.com):

PUT /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
X-Custom-Header: some-value
Content-Type: application/json

{
  "data": "Một số dữ liệu cần được cập nhật"
}

Phản hồi từ Server (từ http://api.example.net):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json

{
  "status": "Dữ liệu đã được cập nhật thành công"
}

Các Header CORS phổ biến

Dưới đây là phân tích các header CORS chính mà bạn cần hiểu:

CORS trong các Ngôn ngữ Phía Máy chủ Khác nhau

Việc triển khai CORS thường bao gồm việc cấu hình ứng dụng phía máy chủ của bạn để gửi các header CORS thích hợp. Dưới đây là các ví dụ về cách thực hiện điều này trong các ngôn ngữ và framework khác nhau:

Node.js với Express

Bạn có thể sử dụng gói middleware cors:

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

const app = express();

// Bật CORS cho tất cả các nguồn gốc (THẬN TRỌNG KHI SỬ DỤNG TRONG PRODUCTION)
app.use(cors());

// Hoặc, cấu hình CORS cho các nguồn gốc cụ thể
// app.use(cors({
//   origin: 'http://example.com'
// }));

app.get('/data', (req, res) => {
  res.json({ message: 'Đây là CORS được bật cho tất cả các nguồn gốc!' });
});

app.listen(3000, () => {
  console.log('Máy chủ đang chạy trên cổng 3000');
});

Python với Flask

Bạn có thể sử dụng tiện ích mở rộng Flask-CORS:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

# Hoặc, cấu hình CORS cho các nguồn gốc cụ thể
# CORS(app, resources={r"/api/*": {"origins": "http://example.com"}})

@app.route("/data")
def hello():
    return {"message": "Đây là CORS được bật cho tất cả các nguồn gốc!"}

if __name__ == '__main__':
    app.run(debug=True)

Java với Spring Boot

Bạn có thể cấu hình CORS trong ứng dụng Spring Boot của mình bằng cách sử dụng các annotation hoặc các lớp cấu hình:

Sử dụng Annotation:

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@CrossOrigin(origins = "http://example.com") // Cho phép các yêu cầu từ http://example.com
public class DataController {

    @GetMapping("/data")
    public String getData() {
        return "Đây là CORS được bật cho http://example.com!";
    }
}

Sử dụng Cấu hình:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/data")
                .allowedOrigins("http://example.com") // Cho phép các yêu cầu từ http://example.com
                .allowedMethods("GET", "POST", "PUT", "DELETE")
                .allowedHeaders("*");
    }
}

PHP

 "Đây là CORS được bật cho http://example.com!");
echo json_encode($data);
?>

CORS và các Lưu ý về Bảo mật

Mặc dù CORS cho phép các yêu cầu liên nguồn gốc, việc triển khai nó một cách an toàn là rất quan trọng. Dưới đây là một số lưu ý quan trọng:

Xử lý sự cố CORS

Các vấn đề về CORS có thể gây khó chịu khi gỡ lỗi. Dưới đây là một số vấn đề phổ biến và cách giải quyết chúng:

Công cụ Gỡ lỗi:

Các Kịch bản CORS Nâng cao

Mặc dù các khái niệm CORS cơ bản tương đối đơn giản, có một số kịch bản nâng cao hơn cần xem xét:

Các Thực hành Tốt nhất về CORS

Để đảm bảo triển khai CORS an toàn và hiệu quả, hãy tuân theo các thực hành tốt nhất sau:

Kết luận

CORS là một cơ chế bảo mật quan trọng cho phép các yêu cầu liên nguồn gốc có kiểm soát trong các ứng dụng web. Hiểu cách CORS hoạt động và cách cấu hình nó đúng cách là điều cần thiết đối với mọi nhà phát triển web. Bằng cách tuân theo các hướng dẫn và thực hành tốt nhất được nêu trong hướng dẫn toàn diện này, bạn có thể xây dựng các ứng dụng web an toàn và hoạt động tốt, tương tác liền mạch với các tài nguyên từ các nguồn gốc khác nhau.

Hãy nhớ luôn ưu tiên bảo mật và tránh sử dụng các cấu hình CORS quá thoáng. Bằng cách xem xét cẩn thận các tác động bảo mật của cài đặt CORS của bạn, bạn có thể bảo vệ các ứng dụng và dữ liệu của mình khỏi truy cập trái phép.

Chúng tôi hy vọng hướng dẫn này đã giúp bạn giải mã CORS. Chúc bạn lập trình vui vẻ!