7

Tôi có một WebApi được bảo mật với Basic Auth được áp dụng cho toàn bộ Api bằng cách sử dụng AuthorizationFilterAttribute. Tôi cũng có các Trung tâm SignalR ngồi trên một số Bộ điều khiển Api của tôi.Sử dụng ajaxSetup beforeSend cho Basic Auth đang ngắt kết nối SignalR

Cùng với điều này, tôi có một trang web sử dụng WebApi của tôi. Các trang web chủ yếu viết bằng Backbone, vì vậy để thực hiện cuộc gọi đến WebAPI bảo đảm của tôi, tôi đã thêm jquery sau

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

này hoạt động để giao tiếp với bộ điều khiển Api của tôi, nhưng thêm mã trên đã phá vỡ kết nối với Trung tâm SignalR của tôi, cụ thể:

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

Xóa đường dây jqXHR.setRequestHeader() khôi phục kết nối SignalR Hub nhưng ngắt cuộc gọi Api.

Với trên, tôi có thể làm điều gì đó hacky và chỉ đặt tiêu đề yêu cầu nếu yêu cầu được thực hiện không phải là để/signalr nhưng điều đó chỉ cảm thấy bẩn ...

Có cách nào làm sạch xung quanh này?

Tôi chỉ đang làm điều gì đó ngớ ngẩn? Có ai khác chạy vào điều này không?

Trả lời

7

Điều tôi chưa đề cập trước đây là tôi có DelegatingHandler gửi lại Tiêu đề chính xác cho bất kỳ yêu cầu nào đến WebApi của tôi. Điều này làm việc hoàn hảo cho bất kỳ yêu cầu nào cho WebApi của tôi nhưng tôi đã giả định sai rằng điều này cũng sẽ áp dụng cho các yêu cầu SignalR.

Như SignalR dựa vào phương pháp vận chuyển khác nhau, nó dường như không hợp lý để giả sử tôi có quyền truy cập vào tiêu đề Authorization ở nơi đầu tiên - chúng không phải là một yêu cầu của tất cả các WebSockets triển khai ví dụ (see here)

Giải pháp hiện tại của tôi là sử dụng HubPipeline của SignalR (detailed here). Sử dụng này, tôi tin rằng tôi có thể vượt qua các chứng chỉ cơ bản Auth trong một chuỗi truy vấn và viết một module riêng biệt để xử lý ủy quyền cho các yêu cầu SignalR:


Đi qua chuỗi truy vấn

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

Bộ lọc

public class SignalrBasicAuthFilterAttribute: Attribute, IAuthorizeHubConnection { 

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

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

     return true; 
    } 

} 

Đăng ký t anh Lọc

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

Ngoài ra ...

Lưu ý rằng bởi vì nó không phải là một giả thuyết đáng tin cậy để gửi một tiêu đề ủy quyền với yêu cầu SignalR, vì những lý do nêu trên, tôi vẫn lọc $ .ajaxSetup của tôi để chỉ ảnh hưởng đến phi SignalR yêu cầu:

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

Khi thực hiện việc này, tôi sẽ rời khỏi lớp SignalrBasicAuthFilterThuộc tính để đảm nhận toàn bộ trách nhiệm cho việc ủy ​​quyền yêu cầu SignalR.


Đọc thêm:

+0

Các AuthorizeHubConnection là mảnh tôi nhớ da diết! Cảm ơn!!! – kzfabi

1

Tôi nghĩ giải pháp thực sự cho vấn đề sẽ là đảm bảo rằng "Ủy quyền" là một phần của tiêu đề được phép (Access-Control-Allow-Headers) được trả về từ phản hồi signalR cho yêu cầu "thương lượng".

Bạn có thể đăng ký tiêu đề trong web.config giống như khả năng này.

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