对未经身份验证的用户和AJAX调用的不同响应

时间:2010-10-22 19:50:20

标签: asp.net-mvc ajax

我的ASP MVC(1.0)网站有一个默认登录页面(基于OpenId - 但不应该有所不同)。当AuthorizedAttribute在Action / Controller上时,它可以正常工作。

但是,我也有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设置为Unauthorized,请求将被重定向到我的登录页面,这对Ajax请求不利。

对此问题的任何建议表示赞赏。

3 个答案:

答案 0 :(得分:5)

这是一个常见问题。

Authorize属性返回Http 401 Unauthorized响应。不幸的是,如果你启用了FormsAuthentication,那么401会被FormsAuthenticationModule截获,然后执行重定向到登录页面 - 然后将Http 200(和登录页面)返回给你的ajax请求。

最好的替代方法是修改授权代码以返回不同的Http状态代码 - 比如403 - formAuthenticationModule没有捕获它,你可以捕获Ajax方法。

答案 1 :(得分: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" });
  }
}

答案 2 :(得分: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;
    }

});