2009-12-10 51 views
6

我們擁有受窗體身份驗證保護的ASP.NET應用程序。該應用程序大量使用MS AJAX來調用其Web服務。來自AJAX的表單身份驗證和POST請求

當表單身份驗證超時並且發生請求時 - 一切正常(用戶重定向到登錄頁面)。

當窗體身份驗證超時和POST -request發生(AJAX) - 無重定向發生,而不是應用程序返回「401 unathorized」,瀏覽器會提示輸入用戶名和密碼(不是登錄表單,而是瀏覽器內置的對話框)。當然輸入任何用戶名/密碼永遠不會有幫助。

我該如何處理?

更新:用螢火蟲看後,我發現定期POST請求重定向到登錄罰款,它只是網絡服務調用,拋出「401 Unauthorizes」。 常規請求和網絡服務之間的區別是URL。這是「page.aspx」對於一個普通請求後和「service.asmx /方法名」爲web服務...

+1

你用FireBug看了看實際發送到服務器的是什麼以及它迴應了什麼?瀏覽器的內置提示通常表示您嘗試訪問的資源受基本或NTLM身份驗證的保護。你的網站部分是否啓用了這種認證? – 2009-12-10 07:29:24

+0

是的,在IIS設置中我們有「windows集成」身份驗證(以及「匿名訪問」)。謝謝,我會嘗試螢火蟲 – Alex 2009-12-10 08:00:46

回答

2

好的,回答我自己的問題。

尋找到這個問題,並研究多一點後,我發現,當一個web應用程序是通過表單的身份驗證保護和用戶未通過身份驗證,這是發生了什麼:

  • 如果它是GET請求 - 用戶被重定向到登錄頁面 。
  • 如果這是對頁面的POST請求 - 用戶是 重定向到登錄頁面。
  • 如果它是一個POST請求到Web服務 - 在 用戶得到401不正當

那如何ASP。NET工程

如果一個Web服務被AJAX(xmlHttpRequest對象)調用並返回401 - 當然瀏覽器顯示一個彈出登錄框。

現在,你應該做的是添加一些代碼到Application_PostAuthenticateRequest,這將防止投擲401的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,你可以指向一些doucmentation,談論的401狀態代碼的Web服務,我有一個場景,我正在檢查會議ecpiry和我做重定向,結果401到客戶端 – 2009-12-31 13:17:31

+0

Response.End通常是壞事要做。通常你想'response.Redirect(url,False); HttpContext.Current.ApplicationInstance.CompleteRequest();' – 2014-09-02 15:16:39

1

我看到兩個解決方案:

(1)「心跳」機制。在每個頁面包含一個腳本,將「平」通過一些虛擬Ajax請求的服務器,如:

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

這樣的會議應該不是隻要在瀏覽器窗口打開時到期。

(2)在每個ajax請求上檢查響應的狀態。如果響應中有「401未經授權」代碼(或其他與200不同的代碼),則表示會話過期,而不是將響應加載到頁面中的某個對話框中,而是將用戶重定向到登錄頁面。

結論基於評論:

最好的解決辦法是上述兩種機制結合起來。只要頁面顯示在瀏覽器中,心跳機制將有助於保持會話的活動。但是並不能保證。當會話過期時,到服務器的連接可能中斷並重新打開。所以你應該檢查響應狀態。

+0

你可以只做'setInterval(ping,60000);'不推薦傳遞一個字符串給setInterval,因爲它等價於eval() – 2009-12-10 07:29:30

+0

你還需要在ping()中再次調用setInterval。如果您希望它運行多次 – 2009-12-10 07:30:16

+0

除了200以外的任何其他代碼並不意味着會話已過期。 – 2009-12-10 07:35:25