2017-09-27 84 views
0

我在我的asp.net mvc应用程序中覆盖了HandleUnauthorizedRequest方法,以确保它向未经授权的Ajax调用发送401响应,而不是重定向到登录页面。当我在本地运行它时,它的工作状态非常好,但是我部署到IIS后,我的重写方法不会被调用。调试点根本不打我的方法,并立即被重定向到登录页面。部署到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请求或一个简单的页面刷新后登录会话已过期 -

  1. 我部署将该网站放到我的本地IIS上
  2. 登录网站,进入主页 - “/ Home”
  3. 右键单击“注销”链接,“在新选项卡中打开” - 确保主页仍在当前标签上打开,而 会话被记录ou吨。
  4. 刷新主页。现在在这里,调试点应该打开我覆盖的HandleUnauthorizedRequest方法,并通过 if/else条件,然后将我重定向到登录页面。但它 不!它只是简单地重定向到登录页面。我是 认为它甚至没有考虑我的自定义授权属性。

但是,当我从Visual Studio运行该网站时,一切正常,控制进入我的覆盖方法的调试点,并通过if/else条件。

+0

'一旦部署到IIS后会有什么不同?'''ConfigurationManager.AppSettings [“LoginUrl”]' - 你检查了你的配置文件吗? – NightOwl888

+0

是的,我检查,它指向“帐户/登录”。但问题是,在部署到IIS后,即使我完全删除了“LoginUrl”的配置设置,它仍然会重定向到“帐户/登录”,该控件甚至不会输入我的自定义属性的'HandleUnauthorizedRequest'方法只有在我部署之后。我尝试在调试和发布配置中部署,但同样的问题 –

回答

0

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

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