【问题标题】:Asp.net Mvc custom mechanism to handle unauthorized requestAsp.net Mvc 自定义机制来处理未经授权的请求
【发布时间】:2016-11-28 18:44:51
【问题描述】:

对于我的网站,我希望安全控制器(或操作)的以下行为

如果用户发出正常请求重定向到登录页面(我很容易做到)

如果请求是Ajax类型Request.IsAjaxRequest()==true,返回状态码401

如何为此创建过滤器??

【问题讨论】:

  • 我找不到方法。在 ajax 请求中,当我执行此操作时 Response.StatusCode = (int)HttpStatusCode.Unauthorized; ,它将我重定向到我不想要的登录页面。

标签: asp.net-mvc security asp.net-mvc-3 asp.net-mvc-2 unauthorized


【解决方案1】:
 public class MyCustomAuthorize : AuthorizeAttribute
{
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            //if ajax request set status code and end Response
            if (filterContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.HttpContext.Response.StatusCode = 401;
                filterContext.HttpContext.Response.End();
            }

            base.HandleUnauthorizedRequest(filterContext);
        }
}

像上面一样创建一个过滤器,如果通过 ajax 发出请求,它将返回未授权请求的状态代码 401。

如果你使用 jQuery,你可以这样做

jQuery.ajax({
statusCode: {
    401: function() {
      alert('unauthrized');
    },

  /*other options*/
});

【讨论】:

  • 非常优雅的解决方案。比 SO 上的其他解决方案要好得多。 +1
  • 这样做会引发 HTTPException:“发送 HTTP 标头后服务器无法设置状态。”此属性是否需要与其他操作过滤器相关的运行顺序?
  • @Marchy 如果你删除filterContext.HttpContext.Response.End(); 行,异常就会消失。虽然我不确定还有什么会受到影响,但我想知道这条线的用途。
  • @Dmitry 如果你删除 filterContext.HttpContext.Response.End();状态码将为 200
  • @Marchy 你忘记最后一行了吗? base.HandleUnauthorizedRequest(filterContext); 我有同样的问题只是因为没有执行这一行。
【解决方案2】:

除了接受的答案之外,我还需要放入这行代码以防止 FormsAuthentication 重定向到登录页面..

filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;

然后我删除了 filterContext.HttpContext.Response.End();

var unauthorizedResult = new JsonResult
{
    Data = new ErrorResult() {Success = 0, Error = "Forbidden"},
            JsonRequestBehavior = JsonRequestBehavior.AllowGet
    };
    // status code
    filterContext.HttpContext.Response.StatusCode = (int) HttpStatusCode.Unauthorized;
    // return data
    filterContext.Result = unauthorizedResult;
    filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
}

【讨论】:

    【解决方案3】:

    您的问题不在于 AJAX 请求,您的问题是返回 HTTP 401 Unauthorized 响应,因为您使用表单身份验证。此响应代码告诉框架它应该使用 HTTP 302 响应将用户代理重定向到您的登录页面。这就是为什么设置“正常”请求重定向很容易的原因 - 它是自动完成的。
    为了回答你的问题,我遇到了类似的问题,我最终得到的解决方案是不使用表单身份验证。我实现了一个自定义授权属性,改为手动处理这两种情况。我不确定这是否是最好的方法,但它确实有效。我对其他人对此解决方案的看法或存在哪些其他解决方案感兴趣。
    幸运的是,您仍然可以使用 FormsAuthentication 类为您处理 cookie,但您必须从 Web.config 文件中删除表单身份验证配置。当用户登录时,您使用FormsAuthentication.SetAuthCookie 来设置一个cookie(您可能已经这样做了)。其次,在您的授权属性中,您从请求中获取 cookie 并使用FormsAuthentication.Decrypt 对其进行解密。如果它存在并且有效,则基于此 cookie 在HttpContext 中设置用户,因为表单身份验证将不再为您执行此操作。如果不是,您要么重定向到登录页面,要么返回 401,这取决于它是否是 AJAX 调用。

    【讨论】:

      【解决方案4】:

      你可以使用ajaxonly来限制对ajax actionresult的访问

      【讨论】:

        【解决方案5】:

        你可以只返回一个 HttpUnauthorizedResult

        注意:这可能会导致 MVC 框架将您返回到登录页面。

        public ActionResult FailResult()
        {
                return new HttpUnauthorizedResult();
        }
        

        【讨论】:

          【解决方案6】:

          一种简单的方法是在登录操作中进行检查

          public ActionResult SignIn()
          {
              if (Request.IsAjaxRequest())
              {
                  // you could return a partial view that has this script instead
                  return Content("<script>window.location = '" + Url.Action("SignIn", "Account") + "'</script>");
              }
             ...
             return View();
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-07-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-11-01
            • 2010-11-01
            相关资源
            最近更新 更多