CORS - Làm cách nào để 'đánh dấu trước' một httprequest?


94

Tôi đang cố gắng thực hiện một yêu cầu HTTP tên miền chéo tới dịch vụ WCF (mà tôi sở hữu). Tôi đã đọc một số kỹ thuật để làm việc với các giới hạn của kịch bản miền chéo. Vì dịch vụ của tôi phải đáp ứng cả yêu cầu GET và POST nên tôi không thể triển khai một số thẻ tập lệnh động có src là URL của yêu cầu GET. Vì tôi có thể tự do thực hiện các thay đổi tại máy chủ, nên tôi đã bắt đầu cố gắng triển khai một giải pháp bao gồm việc định cấu hình phản hồi của máy chủ để bao gồm tiêu đề "Access-Control-Allow-Origin" và các yêu cầu 'preflight' với và yêu cầu OPTIONS. Tôi lấy ý tưởng từ bài đăng này: Bắt CORS hoạt động

Ở phía máy chủ, phương pháp web của tôi đang thêm 'Access-Control-Allow-Origin: *' vào phản hồi HTTP. Tôi có thể thấy rằng các câu trả lời hiện có bao gồm tiêu đề này. Câu hỏi của tôi là: Làm cách nào để 'đánh dấu trước' một yêu cầu (TÙY CHỌN)? Tôi đang sử dụng jQuery.getJSON để thực hiện yêu cầu GET nhưng trình duyệt hủy yêu cầu ngay lập tức với sự nổi tiếng:

Nguồn gốc http: // localhost không được Access-Control-Allow-Origin cho phép

Có ai quen thuộc với kỹ thuật CORS này không? Những thay đổi nào cần được thực hiện ở khách hàng để đáp ứng yêu cầu của tôi?

Cảm ơn!

Câu trả lời:


158

Trong yêu cầu preflight, bạn sẽ thấy hai tiêu đề sau: Access-Control-Request-Method và Access-Control-Request-Headers. Các tiêu đề yêu cầu này đang yêu cầu máy chủ cấp quyền để thực hiện yêu cầu thực tế. Phản hồi preflight của bạn cần xác nhận các tiêu đề này để yêu cầu thực sự hoạt động.

Ví dụ: giả sử trình duyệt đưa ra yêu cầu với các tiêu đề sau:

Origin: http://yourdomain.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-Custom-Header

Sau đó, máy chủ của bạn sẽ phản hồi với các tiêu đề sau:

Access-Control-Allow-Origin: http://yourdomain.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: X-Custom-Header

Đặc biệt chú ý đến tiêu đề phản hồi Access-Control-Allow-Headers. Giá trị của tiêu đề này phải giống với các tiêu đề trong tiêu đề yêu cầu Access-Control-Request-Headers và không được là '*'.

Sau khi bạn gửi phản hồi này tới yêu cầu khởi hành, trình duyệt sẽ đưa ra yêu cầu thực tế. Bạn có thể tìm hiểu thêm về CORS tại đây: http://www.html5rocks.com/en/tutorials/cors/


bạn có thể thêm nhiều miền vào Access-Control-Allow-Origin không?
botbot 17/12/12

@botbot Bạn có thể làm việc ra điều này bằng cách bây giờ nhưng trong trường hợp những người khác đang tự hỏi có thể làmAccess-Control-Allow-Origin: *
Steve Chambers

2
Tôi có thể đã bỏ lỡ một cái gì đó. Vì vậy, tôi có nên gửi hai yêu cầu XMLHttp không? Một cho chuyến bay trước; kiểm tra phản hồi về thành công và sau đó gửi truy vấn thực tế?
Kangkan

14
@Kangkan bạn không cần phải lo lắng về việc gửi yêu cầu preflight. Nếu yêu cầu cần được thông báo trước, trình duyệt sẽ gửi yêu cầu đó cho bạn.
thưa ông,

4
Cảm ơn bạn đã 'trả đặc biệt chú ý là một chút ... mà giải quyết vấn đề của tôi với nút / expressjs tôi đã có thể để thêm một bộ lọc để nắm bắt những yêu cầu này preflight//cors and preflight filtering app.all('*', function(req, res, next){.. //preflight needs to return exact request-header res.set('Access-Control-Allow-Headers', req.headers['access-control-request-headers']); if ('OPTIONS' == req.method) return res.send(204);next(); });
Kurtfm

0

Mặc dù chủ đề này có từ năm 2014, vấn đề vẫn có thể xảy ra với nhiều người trong chúng ta. Đây là cách tôi xử lý nó trong ngữ cảnh jQuery 1.12 / PHP 5.6:

  • jQuery đã gửi yêu cầu XHR chỉ sử dụng các tiêu đề hạn chế; chỉ có 'Nguồn gốc' đã được gửi.
  • Không cần yêu cầu trước chuyến bay.
  • Máy chủ chỉ phải phát hiện một yêu cầu như vậy và thêm "Access-Control-Allow-Origin:". Tiêu đề $ _SERVER ['HTTP_ORIGIN'], sau khi phát hiện đây là XHR nhiều nguồn gốc.

Mẫu mã PHP:

if (!empty($_SERVER['HTTP_ORIGIN'])) {
    // Uh oh, this XHR comes from outer space...
    // Use this opportunity to filter out referers that shouldn't be allowed to see this request
    if (!preg_match('@\.partner\.domain\.net$@'))
        die("End of the road if you're not my business partner.");

    // otherwise oblige
    header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
}
else {
    // local request, no need to send a specific header for CORS
}

Đặc biệt, không thêm dấu exit;vì không cần khởi hành.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.