2012-06-24 32 views
18

Tôi đang làm việc trên một ứng dụng, nơi máy chủ và ứng dụng khách tiêu dùng nằm trong các miền khác nhau, vì vậy tôi muốn sử dụng CORS. Để làm như vậy, tôi phải thiết lập tiêu đề http tương ứng trong phản ứng máy chủ:Cách gửi tiêu đề CORS với Devise nếu người dùng không được phép (phản hồi 401)

def cors_set_access_control_headers 
    headers['Access-Control-Allow-Origin'] = 'http://localhost' 
    headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS' 
    headers['Access-Control-Allow-Headers'] = '*, X-Requested-With, X-Prototype-Version, X-CSRF-Token, Content-Type' 
    headers['Access-Control-Max-Age'] = "1728000" 
end 

Phương pháp này được sử dụng như một before_filter trong ApplicationController.

Đối với một số tài nguyên, người dùng phải được xác thực và ủy quyền. Yêu cầu được thực hiện thông qua XHR/Ajax. Vì vậy, nếu người dùng không được xác thực Devise sẽ gửi phản hồi 401 cho khách hàng, thay vì chuyển hướng đến trang đăng nhập. Nhưng bộ lọc để đặt tiêu đề CORS không được sử dụng cho phản hồi đó. Do đó, phản hồi 401 không được gửi cho khách hàng. Tôi muốn nắm bắt và sử dụng phản hồi 401 trong ứng dụng khách.

Hiện nay tôi đang sử dụng một cách giải quyết bằng cách không sử dụng các phương pháp xác thực lập mưu, nhưng một đoạn tùy chỉnh auth:

def authenticate_cors_user 
    if request.xhr? && !user_signed_in? 
    error = { :error => "You must be logged in." } 
    render params[:format].to_sym => error, :status => 401 
    end 
end 

này được thiết lập như một before_filter trong ApplicationController, quá. Bằng cách này, bộ lọc để đặt tiêu đề CORS được kích hoạt và mọi thứ hoạt động tốt.

Tôi muốn sử dụng hành vi mặc định của Devise, nhưng các tiêu đề CORS sẽ phải được đặt trong phản hồi 401. làm như thế nào? Tôi có phải định cấu hình warden cho điều đó không?

Làm cách nào để các tiêu đề CORS được đặt cho phản hồi 401 do Devise tạo ra thay vì tạo phản hồi của riêng tôi?

+0

Tôi vẫn không có một giải pháp cho điều đó. Để cung cấp thêm một số ngữ cảnh, hãy xem bài đăng trên blog của tôi về cách tôi đang sử dụng: http://nils-blum-oeste.net/cors-api-with-oauth2-authentication-using-rails-and-angularjs –

Trả lời

21

Tôi sử dụng thành công các rack CORS đá quý https://github.com/cyu/rack-cors và nêu kinh nghiệm của tôi trên my blog.

Punchline: Xác định trật tự middleware để CORS handler là trước khi cai:

config.middleware.insert_before Warden::Manager, Rack::Cors 
+0

Cách tiếp cận của bạn hoạt động tốt, cảm ơn! Tuy nhiên, kỳ lạ, phải mất một thời gian và một số nghiên cứu bổ sung để nhận ra, rằng tôi thực sự phải thay đổi chỉ một dòng mã trong cấu hình để làm cho 'Devise' và' rack-cors' làm việc cùng nhau. –

+0

Hey @ digger69. Bạn có gặp vấn đề với các trường hợp ngoại lệ khác không? Ví dụ: nếu tôi ném một ngoại lệ trong hành động 'def index; tăng 'lỗi'; end' - Rails không trả về các tiêu đề CORS (rack-cors). Nó làm việc cho bạn? –

+4

PS: Bạn cũng có thể sử dụng 'config.middleware.insert 0, Rack :: Cors' để đảm bảo rằng' Rack :: Cors' sẽ được chèn vào trước bất kỳ phần mềm trung gian nào khác có thể. –

0

Chúng tôi thường không thích các tiêu đề CORS. Chúng tôi thích sử dụng HAProxy để chuyển hướng.

Với HAProxy bạn có thể thiết lập tất cả các yêu cầu đến trang web.com/api/ để được chuyển hướng nội bộ đến máy đường ray của bạn.

frontend main *:80 
    acl api  path_beg -i /api 
    acl app  path_beg -i /app 
backend app_backend 
    reqrep ^([^\ ]*)\ /app/(.*) \1\ /\2 
    balance roundrobin 
    server app_files smartphoneapp.localhost:8000 
backend api_backend 
    reqrep ^([^\ ]*)\ /api/(.*) \1\ /\2 
    balance roundrobin 
    server app_api localhost:3000 
+0

CORS có thể bị lừa bằng cách sử dụng một proxy, chắc chắn. Nhưng vẫn phải có một cách để xử lý điều này một cách độc đáo với Devise/warden, tôi đoán vậy. –

+0

Hãy xem bài viết này: http://www.tsheffler.com/blog/?p=428 – Hendrik

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