自定义授权属性返回403页而不是Json对象

时间:2018-01-24 20:43:17

标签: json ajax asp.net-mvc asp.net-mvc-5 authorize-attribute

我创建了一个自定义授权属性,我已将其应用于多个控制器。我现在发现我需要处理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对象?

1 个答案:

答案 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指出我正确的方向。