在MVC3中抛出错误页--HttpException

最近在用MVC实现一些权限管理方面的东西,大概思路是继承AuthorizeAttribute写了一个子类UserAuthorizeAttribute,在需要验证的Action或controller中引用该Attribute。重写了三个方法,依执行顺序分别是OnAuthorization -> AuthorizeCore -> HandleUnauthorizedRequest。


在OnAutorization中获取特性标记的方法的区域名、控制器名、操作方法名。在AuthorizeCore中判断用户是否已经登陆,若没登陆直接返回false,如果登陆则判断该用户对应的areaName、controllerName、actionName是否有访问权限(记录在数据库),有则返回true,否则设置Response.StatusCode=403,并返回false。

在HandleUnauthorizedRequest中判断如果Response.StatusCode==403则提示用户没该权限,否则调用base.HandleUnauthorizedRequest跳转到登陆页。


        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            actionName = filterContext.ActionDescriptor.ActionName;
            controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
            areaName = filterContext.RouteData.DataTokens["area"] as string;

            base.OnAuthorization(filterContext);
        }

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (httpContext == null)
                throw new ArgumentNullException("HttpContext");

            if (!httpContext.User.Identity.IsAuthenticated) return false;//没有登陆
            ActionRoles = ServiceFactory.SystemModuleService.GetActionRoles(actionName, controllerName, areaName);
            UserRoles = HttpContextHelper.GetCurrentUserRoles();//获取当前用户角色

            if (ActionRoles != null && UserRoles != null &&
                UserRoles.Any(x => ActionRoles.Contains(x))) return true;

            httpContext.Response.StatusCode = 403;
            return false;
        }

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (filterContext == null) throw new ArgumentNullException("filterContext");

            //if(filterContext.HttpContext.Request.IsAjaxRequest())

            switch (filterContext.HttpContext.Response.StatusCode)
            {
                case 403:
                    filterContext.Result = new RedirectResult("~/Error/Forbidden");
                    break;
                default:
                    base.HandleUnauthorizedRequest(filterContext);
                    break;

            }
        }


其中在HandleUnauthorizedRequest中直接跳转到"~/Error/Forbidden",总给我一种很莫名的感觉,理想中是出现下图这样的效果,然后由web.config中指定的customError去处理:

http403

尝试过用设置filterContext.Result=new HttpUnauthorizedResult()或者filterContext.Result=new HttpStatusCodeResult(..),HttpStatusCodeResult都不行,返回的都是空白页面。


后在stackoverflow中找到一篇这样的文章:How to return a view for HttpNotFound() in ASP.Net MVC 3? 才得以解决,其实就是一句话:

                case 403:
                    throw new HttpException(403, "Forbidden");//直接抛出403,由customErrors决定如何处理.


写到这里,惭愧,那个惭愧啊~~~

顺便贴下代码,用烂笔头记下customErrors的设置及具体实现:

        <customErrors mode="On" >
            <error statusCode="400" redirect="~/Error/BadRequest" />
            <error statusCode="403" redirect="~/Error/Forbidden" />
            <error statusCode="404" redirect="~/Error/NotFound" />
            <error statusCode="408" redirect="~/Error/Timeout" />
            <error statusCode="500" redirect="~/Error/InternalServerError" />
            <error statusCode="503" redirect="~/Error/ServiceUnavailable" />
        </customErrors>

我没有设置defaultRedirect是我认为全局的HandleErrorAttribute会引用Share下的Error.cshtml帮我处理。我用一个ErrorController来实现以上错误的处理:

        /// <summary>
        /// 403
        /// </summary>
        public virtual ActionResult Forbidden()
        {
            ViewBag.ExceptionIco = "icon-error-forbidden";
            ViewBag.ErrorDescription = "您所处的用户组没有权限访问该功能。";
            return View("Index");
        }

        /// <summary>
        /// 404
        /// </summary>
        public virtual ActionResult NotFound()
        {
            ViewBag.ExceptionIco = "icon-error-notfound";
            ViewBag.ErrorDescription = "您请求的页面不存在。";
            return View("Index");
        }
        .....



posted @ 2013-05-10 14:42  lenya  阅读(355)  评论(0编辑  收藏  举报