我的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请求不利。
对此问题的任何建议表示赞赏。
答案 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;
}
});