2012-06-15 50 views
3

我的項目我正在使用WIF (但這對於這個問題的上下文並不重要,您可以使用替代框架來處理您的身份驗證問題是關於在執行ajax請求時處理身份驗證失敗的問題)。從ClaimsAuthenticationManager繼承和處理認證儘管如此,在我來說,我已經寫了自定義服務器的邏輯:在使用WIF和jQuery Ajax請求時ASP.NET MVC 3中的會話Cookie過期處理

public override IClaimsPrincipal Authenticate(string resourceName, IClaimsPrincipal incomingPrincipal) 
{ 
    if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated) 
    { 
     // add some custom claims 
    } 
    return incomingPrincipal; 
} 

現在,當我刪除所有會話Cookie,結束然後再輸入任何頁面,我重定向到由WIF提供的登錄頁面,並且我被要求再次登錄。一切都按預期工作。

但是,如果我做一個Ajax請求相反,我有一個錯誤,這是由該截獲:

$(document).ready(function() { 
    $.ajaxSetup({ 
     error: function (XMLHttpRequest, textStatus, errorThrown) {    
      // do something 
     } 
    }); 
}); 

不幸的是XMLHttpRequest對象不返回任何有意義的信息,在此基礎上我可以以其他方式處理這種錯誤。在這種特殊情況下,我只想讓應用程序重定向到登錄頁面 - 正常請求所做的一樣。

enter image description here

雖然AJAX調用執行時,從AuthenticateClaimsAuthenticationManager被調用的方法。 Identity.IsAuthenticated返回false,方法結束並全部完成。即使BaseControllerOnAuthorization方法未被調用,所以我無法將任何狀態傳遞給ajax結果對象。

protected override void OnAuthorization(AuthorizationContext filterContext) 
{ 
    if (filterContext.HttpContext.Request.IsAjaxRequest() && !User.Identity.IsAuthenticated) 
    { 
     //do something, for example pass custom result to filterContext 
    } 
    base.OnAuthorization(filterContext); 
} 

如何解決難題?

回答

6

我發現一些資源這個(看便知的底部),以及與下述溶液混合起來:

在執行Ajax請求,我指定我想回JSON:

$.ajax({ 
    url: action, 
    type: 'POST', 
    dataType: 'json', 
    data: jsonString, 
    contentType: 'application/json; charset=utf-8', 
    success: 
     function (result, textStatus, xhr) { 
     } 
}); 

因爲我的框架處理身份驗證,而令牌到期,它將HTTP狀態302放入響應。因爲我不希望瀏覽器透明地處理302響應,所以我在Global.asax中找到它,並將狀態更改爲200 OK。的方法,另外,我添加標題,指示我來處理特殊的方式這樣迴應:

protected void Application_EndRequest() 
{ 
    if (Context.Response.StatusCode == 302 
     && (new HttpContextWrapper(Context)).Request.IsAjaxRequest()) 
    {     
     Context.Response.StatusCode = 200; 
     Context.Response.AddHeader("REQUIRES_AUTH", "1"); 
    } 
} 

響應內容不正確序列化到JSON,這將導致解析錯誤。錯誤事件被調用時,在其內部進行重定向:

$(document).ready(function() { 
    $.ajaxSetup({ 
     error: function (XMLHttpRequest, textStatus, errorThrown) { 
      if (XMLHttpRequest.getResponseHeader('REQUIRES_AUTH') === '1') { 
       // redirect to logon page 
       window.location = XMLHttpRequest.getResponseHeader('location'); 
      } 
      // do sth else 
     } 
    }); 
}); 

How to manage a redirect request after a jQuery Ajax call這裏How do you deal with AJAX requests when user session expires, or where the request terminates in a 302更多的解釋。

UPDATE:

與此同時,我想通了新的解決方案,在我看來好得多,因爲可以應用到所有的Ajax請求開箱即用(如果他們不明顯重新beforeSend事件) :

$.ajaxSetup({ 
    beforeSend: checkPulse, 
    error: function (XMLHttpRequest, textStatus, errorThrown) { 
     document.open(); 
     document.write(XMLHttpRequest.responseText); 
     document.close(); 
    } 
}); 

function checkPulse(XMLHttpRequest) { 
    var location = window.location.href; 
    $.ajax({ 
     url: "/Controller/CheckPulse", 
     type: 'GET', 
     async: false, 
     beforeSend: null, 
     success: 
      function (result, textStatus, xhr) { 
       if (xhr.getResponseHeader('REQUIRES_AUTH') === '1') { 
        XMLHttpRequest.abort(); // terminate further ajax execution 
        window.location = location; 
       } 
      } 
    }); 
} 

控制器方法可以是任何最簡單的:

[Authorize] 
public virtual void CheckPulse() {} 

Application_EndRequest()保持不變。

相關問題