2012-06-24 11 views
18

Pracuję nad aplikacją, w której serwer i klient korzystający z api znajdują się w różnych domenach, więc chciałbym użyć CORS. Aby to zrobić, trzeba ustawić odpowiednie nagłówki HTTP w odpowiedzi serwera:Jak wysłać nagłówki CORS z Devise, jeśli użytkownik nie jest autoryzowany (odpowiedź 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 

Ta metoda jest stosowana jako before_filter w ApplicationController.

W przypadku niektórych zasobów użytkownik musi zostać uwierzytelniony i autoryzowany. Wnioski są składane za pośrednictwem XHR/Ajax. Jeśli więc użytkownik nie jest uwierzytelniony, Devise wyśle ​​odpowiedź 401 do klienta, zamiast przekierować na stronę logowania. Ale filtr do ustawienia nagłówków CORS nie jest używany do tej odpowiedzi. Zatem odpowiedź 401 nie jest wysyłana do klienta. Chcę złapać i użyć odpowiedzi 401 w kliencie.

Obecnie używam obejścia nie używając metody uwierzytelniania opracowania, ale fragment zwyczaj 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 

ten jest ustawiony jako before_filter w ApplicationController też. W ten sposób uruchamiany jest filtr do ustawiania nagłówków CORS i wszystko działa poprawnie.

Wolałbym użyć domyślnego zachowania Devise, ale nagłówki CORS musiałyby zostać ustawione w odpowiedzi 401. Jak to zrobić? Czy muszę do tego skonfigurować warden?

W jaki sposób można ustawić nagłówki CORS dla odpowiedzi 401 wygenerowanej przez program Devise, zamiast tworzyć własną odpowiedź?

+0

Wciąż nie mam na to rozwiązanie. Aby podać trochę więcej kontekstu, sprawdź mój post na blogu o tym, jak go używam: http://nils-blum-oeste.net/cors-api-with-oauth2-authentication-using-rails-and-angularjs –

Odpowiedz

21

ja z powodzeniem stosowany gem rack Cors https://github.com/cyu/rack-cors i przedstawił swoje doświadczenie na my blog.

Punchline: Określ kolejność middleware tak Cors obsługi jest przed naczelnika:

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

Twoje podejście działa świetnie, dzięki! Jednak, o dziwo, zajęło to trochę czasu i kilka dodatkowych badań, aby zdać sobie sprawę, że naprawdę muszę zmienić tylko jedną linię kodu w konfiguracji, aby "Devise" i "rack-cors" współpracowały ze sobą. –

+0

Hej @ digger69. Czy masz problemy z innymi wyjątkami? Na przykład: jeśli wyrzucę wyjątek w moim indeksie akcji 'def '; podnieść "błąd"; end' - Rails nie zwraca nagłówków CORS (rack-cors). Czy Ci to pasuje? –

+4

PS: Można również użyć 'config.middleware.insert 0, Rack :: Cors', aby zagwarantować, że' Rack :: Cors' zostanie wstawiony przed jakimkolwiek innym możliwym oprogramowaniem pośredniczącym. –

0

Generalnie nie lubiliśmy nagłówków CORS. Preferujemy używanie HAProxy do przekierowań.

Za pomocą HAProxy możesz ustawić wszystkie żądania przychodzące na stronę website.com/api/, aby zostać wewnętrznie przekierowanym na twój automat.

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 could obchodzić za pomocą proxy, jasne. Ale nadal musi istnieć sposób, aby to ładnie poradzić sobie z Devise/Warden, jak sądzę. –

+0

Spójrz na ten artykuł: http://www.tsheffler.com/blog/?p=428 – Hendrik

Powiązane problemy