部署到 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 Rest Api - 放置和删除请求不起作用 ERR_FAILED 403