我创建了一个自定义授权属性,我已将其应用于多个控制器。我现在发现我需要处理Ajax请求并优雅地重定向。
Ronnie's answer这看起来就像我需要的那样,但是我只能获得一个通用的403禁止的html页面而不是JSON对象。
SsoAuthorizeAttribute:
public class SsoAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) {
if (filterContext.HttpContext.Request.IsAjaxRequest()) {
var urlHelper = new UrlHelper(filterContext.RequestContext);
filterContext.HttpContext.Response.StatusCode = 403;
filterContext.Result = new JsonResult {
Data = new {
Error = "NotAuthorized",
SingleSignOn = Site.SSOUrl
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
} else {
filterContext.Result = new RedirectResult(Site.SSOUrl, false);
}
}
public override void OnAuthorization(AuthorizationContext filterContext) {
if (true) {
HandleUnauthorizedRequest(filterContext);
}
}
}
}
使用Javascript:
$(function () {
$(document).ajaxError(function (e, xhr) {
if (xhr.status == 403) {
//xhr.responseText always contains a generic 403 page instead of the JSON object
var response = $.parseJSON(xhr.responseText);
window.location = response.LogOnUrl;
}
});
});
如果我将状态代码更改为200:
filterContext.HttpContext.Response.StatusCode = 200;
它可以像我期望的那样工作。
如何覆盖我遇到的行为,以便我可以返回403状态的JSON对象?
答案 0 :(得分:0)
帖子中描述的行为是网络配置的这一部分的结果:
<system.webServer>
<httpErrors errorMode="Custom">
<remove statusCode="404" />
<error statusCode="404" path="~/Error/NotFound" responseMode="ExecuteURL" />
<remove statusCode="500" />
<error statusCode="500" path="~/Error" responseMode="ExecuteURL" />
</httpErrors>
</system.webServer>
该部分的存在使得能够自动提供通用403页面(可能是因为它具有403的默认路径和模式,即使您没有指定一个)。
更新Web.config以包含403也无法解决问题。这种变化导致404被抛出而不是403(不知道为什么会这样)。
web.config中存在自定义错误,替换
filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
与
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
最终解决了这个问题,允许403返回Json。
工作代码:
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) {
if (filterContext.HttpContext.Request.IsAjaxRequest()) {
var urlHelper = new UrlHelper(filterContext.RequestContext);
filterContext.HttpContext.Response.StatusCode = 403;
filterContext.Result = new JsonResult {
Data = new {
Error = "NotAuthorized",
SingleSignOn = Site.SSOUrl
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
} else {
filterContext.Result = new RedirectResult(Site.SSOUrl, false);
}
}
感谢@CodeFuller指出我正确的方向。