2010-10-22 40 views
2

我的ASP MVC(1.0)網站有一個默認的登錄頁面(基於OpenId - 但不應該有所不同)。當AuthorizedAttribute位於Action/Controller上時它工作正常。對未經驗證的用戶和AJAX調用的不同響應

但是,我也有AJAX請求。這是我與他們無關:

if (Request.IsAjaxRequest()) 
{ 
    if (Request.IsAuthenticated) 
    { 
    // Authenticated Ajax request 
    } 
    else 
    { 
    // Non-authenticated Ajax request. 
    Response.StatusCode = (int)HttpStatusCode.Unauthorized; 
    return Json(new { response = "AUTHENTICATION_FAILED" }); 
    } 
} 

的問題是,如果我設置Response.StatusCode未經授權,請求重定向到我的登錄頁面,這是不好的Ajax請求。

對此問題的任何建議表示讚賞。

回答

5

這是一個常見問題。

Authorize屬性返回Http 401未經授權的響應。不幸的是,如果啓用了FormsAuthentication,則401被FormsAuthenticationModule攔截,然後執行重定向到登錄頁面 - 然後將Http 200(和登錄頁面)返回到您的ajax請求。

最好的選擇是修改您的授權代碼以返回不同的Http狀態代碼 - 比如說403 - 這不是由formsAuthenticationModule捕獲的,您可以捕獲到您的Ajax方法。

+0

聽起來不錯。將嘗試它,謝謝。無論如何,MVC 2或3都會改變嗎? – Khash 2010-10-22 22:20:03

+0

不幸的不是。在MVC2和3中同樣如此。我將它作爲MVC團隊的一個問題提出來,但FormsAuthentication不在他們的責任範圍內 – Clicktricity 2010-10-23 08:24:31

0

解決這個問題的一種方法是添加一個文本來唯一標識登錄頁面,並在AJAX回調中使用它重定向到登錄頁面。下面是使用jQuery全局回調示例代碼....

$(document).bind("ajaxComplete", function(event, response, ajaxOptions) { 
    if (response.status == 200 && response.responseText.match(/LOGIN_PAGE_UNIQUE_KEY/)) { 
     self.location = "/web/login?timeout=1"; 
     return false; 
    } 

}); 
+0

這不是一個好的解決方案,因爲它要求所有的AJAX調用都被改變,而不是使用ASP MVC中的登錄頁框架。 – Khash 2010-10-22 22:17:32

+0

@Khash你不需要改變所有的ajax調用。這是一個全局綁定,可以包含在一個共同的頁面 – 2010-10-22 22:40:22

1

你可以使自己的授權過濾器,從一個框架內在,並覆蓋寫入響應當用戶沒有被授權的功能,如果請求來自ajax,則不設置狀態碼。事情是這樣的:

public class MyAutorizeAttribute : AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     if (filterContext.HttpContext.Request.IsAjaxRequest()) 
      filterContext.Result = new JsonResult() { Data = new { response = "AUTHENTICATION_FAILED" } }; 
     else 
      filterContext.Result = new HttpUnauthorizedResult(); 
    } 
} 

現在你的動作使用新的屬性

[MyAutorize] 
public ActionResult myAction() 
{ 
    if (Request.IsAuthenticated) // You should not need to ask this here 
    { 
     // Authenticated Ajax request 
    } 
    else 
    { 
    // Non-authenticated Ajax request. 
    Response.StatusCode = (int)HttpStatusCode.Unauthorized; 
    return Json(new { response = "AUTHENTICATION_FAILED" }); 
    } 
} 
+0

也許我沒有正確表達我的問題。如果我在自定義屬性或代碼中執行此操作,則無關緊要,事實上將StatusCode設置爲Unauthorize會將客戶端重定向到不是AJAX的登錄頁面。 – Khash 2010-10-22 22:18:47