Triển khai mẫu CORS hỗ trợ nhiều nguồn gốc bằng Node.js và Express

Tram Ho

Thực hiện

Khi tạo một ứng dụng web bằng API REST hoặc khung giao diện người dùng, không có gì lạ khi gặp rắc rối với CORS (Chia sẻ tài nguyên gốc chéo).

hình ảnh.png

CORS là một hạn chế bảo mật đối với JavaScript trong trình duyệt web (giao diện người dùng), có nghĩa là khi sử dụng AJAX hoặc các phương thức khác để thực hiện các yêu cầu HTTP, chỉ các yêu cầu từ cùng một nguồn mới được phép và các yêu cầu từ các nguồn khác nhau sẽ không thành công do CORS sự hạn chế. Không có giới hạn nào đối với các yêu cầu HTTP từ back-end, nhưng nó chỉ áp dụng cho các yêu cầu từ front-end. Để biết thêm thông tin, vui lòng xem tại đây: https://developer.mozilla.org/ja/docs/Web/HTTP/CORS

Nếu cùng một người đang tạo cả API REST và ứng dụng web giao diện người dùng hoặc nếu họ biết rằng các yêu cầu đó sẽ đến, họ có thể muốn bỏ qua hạn chế CORS ở phía API. Đối với điều này, có thể thiết lập API để “cho phép các yêu cầu HTTP từ một nguồn gốc cụ thể”. Cụ thể, bằng cách chỉ định nguồn gốc ( https://allowed-origin.com ) được cho phép và trả về tiêu đề phản hồi HTTP của Access-Control-Allow-Origin: https://allowed-origin.com , nguồn yêu cầu sẽ so sánh nội dung tiêu đề này về nguồn gốc của chính nó và chỉ xử lý bình thường nếu nó khớp (nếu không sẽ có lỗi). Cũng có thể chỉ định “cho phép các yêu cầu từ tất cả các nguồn gốc” và trong trường hợp này, điều này có thể được thực hiện bằng cách trả về tiêu đề phản hồi HTTP đặc biệt của Access-Control-Allow-Origin: * .

Bây giờ, khi phát triển phía trước, bạn có thể gặp phải các vấn đề sau:

  1. Chạy nó trên http://localhost:3000 trong khi phát triển hoặc thử nghiệm.
  2. Sau khi phát triển xong, nó sẽ được sử dụng trong hoạt động thực tế tại https://xxxxx.com .
  3. API REST sẽ không hoạt động trừ khi cài đặt CORS được định cấu hình, điều này khác ở cả (1) và (2).

Khi phát triển, chúng tôi sử dụng máy chủ cục bộ như http://localhost:3000 để kiểm tra mã và khi sản xuất, chúng tôi sử dụng máy chủ internet như https://xxxxx.com để truy cập. Đây không phải là một trường hợp đặc biệt bất thường. Để chạy API REST trong cả môi trường phát triển và sản xuất, sẽ thuận tiện khi thiết lập CORS (bất kể các yêu cầu từ http://localhost:3000 có được phép hay không). Tuy nhiên, có một hạn chế là chỉ có thể chỉ định một Nguồn gốc (và thậm chí không phải là biểu thức chính quy ngoài * ) trong tiêu đề Access-Control-Allow-Origin . Nói cách khác, không thể chỉ định “cho phép yêu cầu từ http://localhost:3000 hoặc https://xxxxx.com ” trong tiêu đề Access-Control-Allow-Origin . Có cách nào để giải quyết vấn đề này và làm cho nó khả thi không?

Một cách khả thi là chỉ định Access-Control-Allow-Origin: * trong quá trình phát triển để cho phép các yêu cầu từ tất cả các nguồn, nhưng đây cũng là một cài đặt rất dễ bị tấn công.

Tôi đã nghĩ ra phương pháp sau: Chuẩn bị trước một mảng có nguồn gốc được phép và nếu nguồn yêu cầu được bao gồm trong mảng nguồn gốc được phép, hãy chỉ định động nguồn gốc trong tiêu đề Access-Control-Allow-Origin và trả lại. Nếu bạn tạo riêng cho môi trường Node.js + Express, nó sẽ như thế này:

// app.js
const express = require ( "express" ) ;
const app = express ( ) ;

app . use ( express . Router ( ) ) ;

var settings_cors = "CORS" in process . env ? process . env . CORS : "" ;
app . all ( "/*" , function ( req , res , next ) {
  if ( settings_cors ) {
    var origin = req . headers . origin ;
    if ( origin ) {
      var cors = settings_cors . split ( " " ) . join ( "" ) . split ( "," ) ;

      // We need to support "*" for cors.
      if ( cors . indexOf ( "*" ) > - 1 ) {
        res . setHeader ( "Access-Control-Allow-Origin" , "*" ) ;
        res . setHeader ( "Vary" , "Origin" ) ;
      } else {
        res . setHeader ( "Access-Control-Allow-Origin" , origin ) ;
        res . setHeader ( "Vary" , "Origin" ) ;
      }
    }
  }
  next ( ) ;
} ) ;

app . get ( "/ping" , function ( req , res ) {
  res . contentType ( "application/json; charset=utf-8" ) ;

  res . write ( JSON . stringify ( { status : true , message : "PONG" } , null , 2 ) ) ;
  res . end ( ) ;
} ) ;

var port = process . env . PORT || 8080 ;
app . listen ( port ) ;
console . log ( "server starting on " + port + " ..." ) ;

Khi khởi động, hãy chỉ định một mảng các nguồn gốc được phép (trong ví dụ này là "http://localhost:3000 ” và ” https://xxxxx.herokuapp.com “) làm biến môi trường CORS, được phân tách bằng dấu phẩy.

(sample)$ CORS=http://localhost:3000,https://xxxxx.herokuapp.com node app

Mẫu này (chạy trên cổng 8080) xác định API REST phản hồi yêu cầu GET /ping với { status: true, message: ‘PONG’ }. Nếu nguồn gốc của yêu cầu là http://localhost:3000 hoặc https://xxxxx.herokuapp.com , thì có thể bỏ qua các giới hạn CORS bằng tiêu đề Access-Control-Allow-Origin .

Có vẻ như chúng ta có thể thiết lập một máy chủ API có thể được sử dụng trong môi trường thử nghiệm, dàn dựng và sản xuất mà không cần thay đổi cài đặt CORS.

Mã nguồn mẫu tôi đã cung cấp ở đây: https://github.com/dotnsf/multicors

Nguồn

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo