7

Mam WebApi zabezpieczony przez Basic Auth, który jest stosowany do całego Api przy użyciu AuthorizationFilterAttribute. Posiadam także SignalR Hubs siedzące na kilku moich kontrolerach Api.Korzystanie z ajaxSetup beforeSend dla Basic Auth zrywa połączenie SignalR

Oprócz tego mam stronę internetową, która korzysta z mojej WebApi. Na stronie internetowej jest przeważnie napisane w kręgosłup, tak aby wykonywać połączenia do mojej zabezpieczonej WebAPI, dodałem następujące jQuery

$.ajaxSetup({ 
    beforeSend: function (jqXHR, settings) { 
     jqXHR.setRequestHeader('Authorization', 'Basic ' + Token); 
     return true; 
    } 
}); 

Działa to do komunikacji z moich kontrolerów api, ale dodając powyższy kod złamał połączenie do mojego SignalR Piasty, a konkretnie:

XMLHttpRequest cannot load http://localhost:50000/signalr/negotiate?_=1366795855194. 
Request header field Authorization is not allowed by Access-Control-Allow-Headers. 

Demontaż linii jqXHR.setRequestHeader() przywraca moją SignalR piasta ale przerywa wywołania aPI.

Biorąc powyższe pod uwagę, mógłby zrobić coś hacky i tylko ustawić nagłówek żądania, jeżeli żądanie jest wykonane nie jest/signalr ale że po prostu czuje się brudna ...

Czy istnieje przejrzysty sposób wokół to?

Czy robię coś głupiego? Czy ktoś jeszcze do tego dołączył?

Odpowiedz

7

Co nie wspominając zanim to, że mam DelegatingHandler który odsyła odpowiednie nagłówki do każdego żądania pochodzące z mojego WebAPI. Działa to doskonale w przypadku wszelkich żądań związanych z moją witryną WebApi, ale błędnie założyłem, że dotyczy to również żądań SignalR.

Jak SignalR opiera się na kilku różnych metod transportu, nie wydaje się rozsądne założenie, mam dostęp do nagłówków zezwolenia w pierwszej kolejności - nie są wymagane od wszystkich WebSockets wdrożeń na przykład (see here)

Moje obecne rozwiązanie polegało na wykorzystaniu HubPipeline SignalR (detailed here). Korzystanie z tego, wierzę, że mogę przekazać poświadczenia Podstawowe uwierzytelniania w ciągu kwerendy i napisać osobny moduł do obsługi autoryzacji dla wniosków SignalR:


Przechodząc ciąg zapytań

$.connection.hub.qs = "auth=" + MyBase64EncodedAuthString; 

Filtr

public class SignalrBasicAuthFilterAttribute: Attribute, IAuthorizeHubConnection { 

    public bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request) { 
     var authString = request.QueryString["auth"]; 

     // ... parse, authorize, etc ... 

     return true; 
    } 

} 

Rejestrowanie t on Filter

var globalAuthorizer = new SignalrBasicAuthFilterAttribute(); 
GlobalHost.HubPipeline.AddModule(new AuthorizeModule(globalAuthorizer, globalAuthorizer)); 

Dodatkowo ...

Zauważ, że ponieważ nie jest wiarygodnym założenie wysłać nagłówek Authorization wniosków SignalR, dla wyżej wymienionych powodów, ja wciąż filtrowanie my $ .ajaxSetup wpływać tylko non-SignalR wnioski:

$.ajaxSetup({ 
    beforeSend: function (jqXHR, settings) { 
     if (settings.url.indexOf("/signalr") == -1) 
      jqXHR.setRequestHeader('Authorization', 'Basic ' + Token); 
     return true; 
    } 
}); 

W ten sposób opuszczam klasę SignalrBasicAuthFilterAttribute, aby przejąć pełną odpowiedzialność za autoryzowanie żądań SignalR.


Dalsze Reading:

+0

AuthorizeHubConnection był kawałek mi brakuje! Dzięki!!! – kzfabi

1

Myślę, że prawdziwym rozwiązaniem problemu będzie upewnienie się, że "autoryzacja" jest częścią dozwolonych nagłówków (nagłówki kontroli dostępu) zwróconych z odpowiedzi signalR dla żądania "negocjowania".

Można zarejestrować nagłówek w pliku web.config, podobnie jak ta możliwość.

<httpProtocol> 
    <customHeaders> 
    <add name="Access-Control-Allow-Headers" value="Authorization" /> 
    </customHeaders> 
</httpProtocol> 
Powiązane problemy