2009-12-10 60 views
6

Chúng tôi có một ứng dụng ASP.NET được bảo vệ bởi xác thực biểu mẫu. Ứng dụng sử dụng MS AJAX rất nhiều để gọi các dịch vụ web của nó.Xác thực biểu mẫu và yêu cầu POST từ AJAX

Khi xác thực biểu mẫu hết giờ và GET -yêu cầu xảy ra - tất cả đều ổn (người dùng được chuyển hướng đến trang đăng nhập).

NHƯNG khi các hình thức xác thực lần ra ngoài và một POST -request xảy ra (ajax) - không chuyển hướng xảy ra, thay vì trở về ứng dụng "401 unathorized" và trình duyệt sẽ nhắc cho tên người dùng và mật khẩu (không phải là một hình thức đăng nhập , nhưng một hộp thoại tích hợp trình duyệt). Tất nhiên, nhập tên người dùng/mật khẩu không bao giờ hữu ích.

Làm cách nào để xử lý việc này?

CẬP NHẬT: Sau khi tìm kiếm bằng firebug, tôi phát hiện ra rằng các yêu cầu POST thường xuyên chuyển hướng để đăng nhập tốt, chỉ có các cuộc gọi dịch vụ web ném "401 Unauthorizes". Sự khác biệt giữa yêu cầu thông thường và dịch vụ web là URL. Đó là "page.aspx" cho một thường xuyên sau yêu cầu và "service.asmx/methodname" cho webservices ...

+1

Bạn đã xem FireBug có thực sự được gửi tới máy chủ hay không và những gì nó phản hồi? Lời nhắc được tạo sẵn của trình duyệt thường có nghĩa là tài nguyên bạn đang cố truy cập được bảo vệ bằng xác thực cơ bản hoặc NTLM. Bạn đã bật xác thực như vậy cho các phần của trang web của mình chưa? –

+0

Có, trong cài đặt IIS, chúng tôi có "cửa sổ tích hợp" authenticaiton trên (cùng với "truy cập ẩn danh"). Cảm ơn, tôi sẽ thử Firebug – Alex

Trả lời

2

Ok, trả lời nhiệm vụ của riêng tôi.

Sau khi xem xét vấn đề này và nghiên cứu một chút tôi càng thấy rằng khi một ứng dụng web được bảo vệ bởi Forms-Authentication và người dùng là không được xác thực, đây là những gì sẽ xảy ra:

  • Nếu đó là yêu cầu GET - người dùng được chuyển hướng đến trang đăng nhập.
  • Nếu đó là yêu cầu POST tới trang - người dùng được chuyển hướng đến trang đăng nhập.
  • Nếu đó là một POST-yêu cầu đến một trang web dịch vụ - người dùng được 401-trái phép

Thats cách ASP.NET hoạt động

Và nếu một dịch vụ web được gọi bởi AJAX (đối tượng xmlHttpRequest) và trả về 401 - tất nhiên trình duyệt hiển thị hộp đăng nhập bật lên.

Bây giờ, bạn nên làm gì thêm một số mã vào Application_PostAuthenticateRequest để ngăn chặn việc ném 401 cho dịch vụ web.

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e) 
{ 
    if (Request.RequestType == "POST" //if its POST 
     && !User.Identity.IsAuthenticated //if user NOT authed 
     && !HasAnonymousAccess(Context) //if it's not the login page 
     ) 
    { 
     //lets get the auth type 
     Configuration config = WebConfigurationManager.OpenWebConfiguration("~"); 
     SystemWebSectionGroup grp = (SystemWebSectionGroup)config.GetSectionGroup("system.web"); 
     AuthenticationSection auth = grp.Authentication; 
     //if it FORMS auth 
     if(auth.Mode== AuthenticationMode.Forms) 
     { 

      //then redirect... this redirect won't work for AJAX cause xmlHttpRequest can't handle redirects, but anyway... 
      Response.Redirect(FormsAuthentication.LoginUrl, true); 
      Response.End(); 

     } 
    } 
} 
public static bool HasAnonymousAccess(HttpContext context) 
{ 
    return UrlAuthorizationModule.CheckUrlAccessForPrincipal(
     context.Request.Path, 
     new GenericPrincipal(new GenericIdentity(string.Empty), null), 
     context.Request.HttpMethod); 
} 
+0

@jazbit, bạn có thể chỉ ra một số doucmentation mà nói về mã trạng thái 401 cho các dịch vụ web, tôi có một kịch bản mà tôi đang kiểm tra cho ecpiry phiên và đang làm một chuyển hướng mà kết quả 401 cho khách hàng –

+0

Response.End thường là một điều xấu phải làm. Thông thường bạn muốn 'response.Redirect (url, False); HttpContext.Current.ApplicationInstance.CompleteRequest(); ' –

1

tôi thấy hai giải pháp: cơ chế

(1) "nhịp tim". Trên mỗi trang bao gồm một kịch bản mà sẽ "ping" máy chủ bởi một số yêu cầu ajax giả, như:

<script> 
    setInterval(ping, 60000); // based on comment by John 
    function ping() 
    { 
     $.get('/do/nothing'); 
    } 
</script> 

Bằng cách này phiên không nên hết hạn miễn là các cửa sổ trình duyệt đang mở.

(2) Trên mỗi yêu cầu ajax, hãy kiểm tra trạng thái của phản hồi. Nếu phản hồi có mã "401 trái phép" (hoặc bất kỳ mã nào khác khác 200), điều đó có nghĩa là phiên đã hết hạn và thay vì tải phản hồi vào một số hộp thoại trong trang chuyển hướng người dùng đến trang đăng nhập.

Kết luận dựa trên nhận xét:

Giải pháp tốt nhất là kết hợp hai cơ chế trên. Cơ chế nhịp tim sẽ giúp giữ cho phiên còn sống miễn là trang được hiển thị trong trình duyệt. Nhưng trong không đảm bảo rằng chắc chắn. Kết nối với máy chủ có thể bị hỏng và mở lại khi phiên hết hạn. Vì vậy, bạn nên kiểm tra trạng thái phản hồi.

+0

bạn có thể thực hiện 'setInterval (ping, 60000);' truyền một chuỗi tới setInterval không được khuyến khích vì nó tương đương với eval() –

+0

Bạn cũng sẽ cần phải gọi setInterval một lần nữa trong ping() nếu bạn muốn nó chạy nhiều hơn một lần –

+0

Bất kỳ mã nào khác ngoài 200 không có nghĩa là phiên đã hết hạn. –

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