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

Posted

技术标签:

【中文标题】部署到 IIS 后自定义授权属性不起作用【英文标题】:Custom authorize attribute doesn't work after deploying to IIS 【发布时间】:2017-09-27 07:24:03 【问题描述】:

我在我的 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请求还是登录会话过期后简单的页面刷新都无所谓——

    我将站点部署到本地 IIS 上 登录网站,进入首页-“/Home” 右键单击“注销”链接,“在新选项卡中打开” - 这可确保主页在当前选项卡上仍然打开,同时 会话已注销。 刷新主页。现在在这里,调试点应该命中我重写的HandleUnauthorizedRequest 方法并通过 if/else 条件,然后将我重定向到登录页面。但它 没有!它只是直接重定向到登录页面。我是 认为它甚至没有考虑我的自定义授权属性。

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

【问题讨论】:

What could be different once it's deployed to IIS? - ConfigurationManager.AppSettings["LoginUrl"] - 你检查你的配置文件了吗? 是的,我检查了,它指向“帐户/登录”。但问题是部署到IIS后,控件甚至没有进入我自定义属性的HandleUnauthorizedRequest方法,即使我完全删除了“LoginUrl”的配置设置,它仍然重定向到“Account/Login”,出现这个问题只有在我部署之后。我尝试在调试和发布配置中进行部署,但同样的问题 【参考方案1】:

当您将网站部署到 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),您将使用默认HttpUnauthorizedResult 实例覆盖您设置的JsonResult 实例。

这些被称为过滤器是有原因的。它们用于过滤进入一段逻辑的请求,而不是实际执行那段逻辑。处理程序(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);
        
    

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

【讨论】:

以上是关于部署到 IIS 后自定义授权属性不起作用的主要内容,如果未能解决你的问题,请参考以下文章

自定义授权过滤器在 ASP.NET Core 3 中不起作用

IIS 7 - Windows 身份验证不起作用[关闭]

IIS Rest Api - 放置和删除请求不起作用 ERR_FAILED 403

URL 重写在 IIS 7 上不起作用

IIS6.0设置了404错误,对htm和aspx、asp都好用,对html不起作用

WebServiceHost在IIS中禁用匿名身份验证后不起作用