部署到IIS后,自定义授权属性不起作用

时间:2017-09-27 07:24:03

标签: c# .net asp.net-mvc iis authorize-attribute

我已经覆盖了我的asp.net mvc应用程序中的HandleUnauthorizedRequest方法,以确保它向未经授权的ajax调用发送401响应,而不是重定向到登录页面。当我在本地运行它时,这非常好用,但是一旦我部署到IIS,我的被覆盖的方法就不会被调用。调试点根本没有触及我的方法,并立即被重定向到登录页面。

这是我的代码:

public class AjaxAuthorizeAttribute : AuthorizeAttribute
    {
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.HttpContext.Response.Clear();
                filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;

                filterContext.Result = new JsonResult
                {
                    Data = new
                    {
                        success = false,
                        resultMessage = "Errors"
                    },
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet
                };
                filterContext.HttpContext.Response.End();
                base.HandleUnauthorizedRequest(filterContext);
            }
            else
            {
                var url = HttpContext.Current.Request.Url.AbsoluteUri;
                url = HttpUtility.UrlEncode(url);
                filterContext.Result = new RedirectResult(ConfigurationManager.AppSettings["LoginUrl"] + "?ReturnUrl=" + url);
            }
        }
    }

我在控制器上声明了属性[AjaxAuthorize]。一旦将其部署到IIS,会有什么不同?

更新 这是我测试的方式,非常简单,在登录会话到期后它是ajax请求还是简单页面刷新无关紧要 - < / p>

  1. 我将网站部署到我的本地IIS
  2. 登录网站,转到主页 - &#34; / Home&#34;
  3. 右键点击&#34;退出&#34;链接,&#34;在新标签页中打开&#34; - 这可确保主页在当前选项卡上仍处于打开状态 会话已注销。
  4. 刷新主页。现在,调试点应该是我的重写HandleUnauthorizedRequest方法,然后通过 if / else条件然后将我重定向到登录页面。但它 没有按&#39;吨!它只是简单地重定向到登录页面。我&#39;米 认为它甚至没有考虑我的自定义授权属性。
  5. 当我从visual studio运行网站时,一切正常,控件在我的重写方法中进入调试点并进入if / else条件。

1 个答案:

答案 0 :(得分:0)

将网站部署到IIS时,默认情况下它将在IIS集成模式下运行。这通常是最好的选择。但这也意味着HTTP请求/响应模型在授权检查期间未完全初始化。我怀疑当您的应用程序托管在IIS上时,这会导致IsAjaxRequest()始终返回false

此外,default HandleUnauthorizedRequest implementation看起来像这样:

    protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        // Returns HTTP 401 - see comment in HttpUnauthorizedResult.cs.
        filterContext.Result = new HttpUnauthorizedResult();
    }

实际上,通过调用base.HandleUnauthorizedRequest(context),您将覆盖使用默认JsonResult实例设置的HttpUnauthorizedResult实例。

有一个原因可以称为过滤器。它们用于过滤进入逻辑的请求,而不是用于实际执行该逻辑。处理程序(ActionResult派生类)应该完成工作。

要实现此目的,您需要构建一个单独的处理程序,以便过滤器执行的逻辑等待,直到HttpContext完全初始化为止。

public class AjaxAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        filterContext.Result = new AjaxHandler();
    }
}

public class AjaxHandler : JsonResult
{
    public override void ExecuteResult(ControllerContext context)
    {
        var httpContext = context.HttpContext;
        var request = httpContext.Request;
        var response = httpContext.Response;
        if (request.IsAjaxRequest())
        {
            response.StatusCode = (int)HttpStatusCode.Unauthorized;

            this.Data = new
            {
                success = false,
                resultMessage = "Errors"
            };
            this.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
            base.ExecuteResult(context);
        }
        else
        {
            var url = request.Url.AbsoluteUri;
            url = HttpUtility.UrlEncode(url);
            url = ConfigurationManager.AppSettings["LoginUrl"] + "?ReturnUrl=" + url;
            var redirectResult = new RedirectResult(url);
            redirectResult.ExecuteResult(context);
        }
    }
}
  

注意:以上代码未经测试。但这应该让你朝着正确的方向前进。