2015-05-22 16 views
17

Tôi đang xây dựng một ứng dụng kiễu góc tương tác với một API được xây dựng với ASP.NET Web API 2. Tôi đang sử dụng Basic Authentication bằng cách gửi một tiêu đề Authorization với mỗi yêu cầu đòi hỏi xác thực:Tránh OPTIONS yêu cầu preflight với CORS

đoạn góc:

$http.defaults.headers.common['Authorization'] = authHeader; 

Yêu cầu:

Accept:application/json, text/javascript 
Accept-Encoding:gzip, deflate, sdch 
Accept-Language:en-US,en;q=0.8 
Access-Control-Max-Age:1728000 
Authorization:Basic [base64 encoded credential couplet here] 
Connection:keep-alive 
DNT:1 
Host: blah.com 
Origin:http://localhost:9000 
Referer:http://localhost:9000/ 
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/53 

Tất cả điều này hoạt động OKAY, nhưng yêu cầu trước OPTIONS được gửi với mọi yêu cầu GET hoặc POST. Điều này ảnh hưởng lớn đến tốc độ cảm nhận của ứng dụng. Tôi đã thực hiện rất nhiều đọc trên CORS "Yêu cầu đơn giản" và có vẻ như là để tránh các yêu cầu preflight OPTIONS preflight là để tránh thêm bất kỳ tiêu đề tùy chỉnh trong các yêu cầu của tôi. Tôi đã thử rất nhiều nội dung khác như gửi Content-Type của text/plain, nhưng có vẻ như tiêu đề Cấp quyền là điều vi phạm yêu cầu "Yêu cầu đơn giản" của CORS.

Vì vậy, có vẻ như tôi có thể phải di chuyển API để sử dụng xác thực/ủy quyền dựa trên mã thông báo. Để tránh các yêu cầu preflight, có vẻ như tôi sẽ cần đặt mã thông báo trong chuỗi truy vấn. Điều này là okay vì nó chỉ là một ứng dụng web nội bộ nhỏ mà sẽ chỉ được truy cập bởi một vài người dùng anyway. Tôi dự định sẽ thực hiện bộ nhớ đệm trên các phản hồi của bộ điều khiển. Vì mỗi yêu cầu đối với một hành động điều khiển sẽ có một mã thông báo khác nhau trong chuỗi truy vấn dựa trên người dùng được xác thực hiện tại, điều này có khiến cho việc lưu vào bộ nhớ cache vô dụng không?

Vì vậy:

  1. Làm thế nào để tránh yêu cầu preflight (sử dụng tiêu đề tùy chỉnh Authorization nếu có thể)
  2. Nếu 1.) là không thể, và tôi di chuyển vào mã thông báo dựa auth, tôi sẽ không thể các phản hồi API bộ nhớ cache cho các hoạt động của bộ điều khiển
  3. Các phương pháp được sử dụng rộng rãi nhất để tránh các yêu cầu preflight mà còn để xác thực người dùng một cách an toàn là gì?

nb Tôi biết có một vài chủ đề khác trên SO và các nơi khác trên web về vấn đề này, nhưng không ai trong số họ có xu hướng cung cấp một câu trả lời dứt khoát về việc liệu nó có thể để tránh yêu cầu preflight cho GET s và POST s khi sử dụng các tiêu đề ủy quyền tùy chỉnh HTTP.

+1

1.) Hiện chưa khả thi trên tất cả các trình duyệt và phương thức HTTP: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests – tyler

+1

Bạn sẽ có thể sử dụng [XMLHttpRequest withCredentials] (https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials) để gửi yêu cầu không được đặt trước bằng cookie ủy quyền. – dave

Trả lời

10

Tôi nghĩ bài này (How to apply CORS preflight cache to an entire domain) khá nhiều nói lên tất cả - không có nhiều bạn có thể làm về vấn đề này

Một giải pháp đơn giản là thêm một reverse proxy để proxy/webserver phục vụ ứng dụng góc của bạn (ví dụ: nginx) để định tuyến các cuộc gọi RESTful của bạn qua cùng một miền, ví dụ: appdomain.com/api -> apidomain.com.

+1

Cảm ơn Reto! Mặc dù tôi đã yêu thích để sắp xếp ra toàn bộ điều preflight một cách thích hợp, cuối cùng tôi đã chọn câu trả lời này. Nó chỉ ra rằng bạn có thể thiết lập một proxy ngược trong IIS và trong một trang web Azure để khách hàng của tôi cũng sẽ được lưu trữ trong một ứng dụng web Azure với chuyển tiếp các yêu cầu '/ api' cục bộ lên ứng dụng web Azure khác lưu trữ API. Tham khảo: http://ruslany.net/2014/05/using-azure-web-site-as-a-reverse-proxy/ – adaam

2

Một giải pháp khác có vẻ hoạt động tốt cho tôi. Thay vì thiết lập proxy và cần định tuyến đến cùng một miền, có thể trả lại yêu cầu preflight trực tiếp từ nginx và do đó giảm thời gian yêu cầu preflight xuống chỉ còn vài phần nghìn giây.

Dưới đây là một đoạn mã đơn giản có thể được sử dụng với nginx.

location/{ 
    if ($request_method = 'OPTIONS') { 
     add_header 'Access-Control-Allow-Origin' '*'; 
     add_header 'Access-Control-Allow-Credentials' 'true'; 
     add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; 
     add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization'; 
     add_header 'Access-Control-Max-Age' 1728000; 
     add_header 'Content-Type' 'text/plain charset=UTF-8'; 
     add_header 'Content-Length' 0; 
     return 204; 
    } 
} 

Sau khi yêu cầu preflight là thành công, đó là sau đó có thể add đơn giản "Access-Control-Allow-Origin" và các công cụ cần thiết khác để các 'GET', yêu cầu 'POST', vv ...

Các vấn đề liên quan