在ASP.NET MVC中重定向未授权的控制器

我在ASP.NET MVC中有一个控制器,我只限于管理员角色:

[Authorize(Roles = "Admin")]
public class TestController : Controller
{
   ...

如果不属于管理员角色的用户导航到此控制器,他们将会看到空白屏幕。

我想要做的就是将它们重定向到View,它说“你需要担任Admin角色才能访问这个资源。”

我想到的一种做法是检查IsUserInRole()上的每个操作方法,如果不在角色中,则返回此信息视图。 但是,我必须在每个打破DRY负责人的操作中加入这个操作,而且显然很难维护。


根据AuthorizeAttribute创建一个自定义授权属性并覆盖OnAuthorization以执行检查如何完成。 通常,如果授权检查失败,AuthorizeAttribute会将筛选结果设置为HttpUnauthorizedResult。 您可以将它设置为ViewResult(您的错误视图)。

编辑 :我有几个博客文章进入更多的细节:

  • http://farm-fresh-code.blogspot.com/2011/03/revisiting-custom-authorization-in.html
  • http://farm-fresh-code.blogspot.com/2009/11/customizing-authorization-in-aspnet-mvc.html
  • 例:

        [AttributeUsage( AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false )]
        public class MasterEventAuthorizationAttribute : AuthorizeAttribute
        {
            /// <summary>
            /// The name of the master page or view to use when rendering the view on authorization failure.  Default
            /// is null, indicating to use the master page of the specified view.
            /// </summary>
            public virtual string MasterName { get; set; }
    
            /// <summary>
            /// The name of the view to render on authorization failure.  Default is "Error".
            /// </summary>
            public virtual string ViewName { get; set; }
    
            public MasterEventAuthorizationAttribute()
                : base()
            {
                this.ViewName = "Error";
            }
    
            protected void CacheValidateHandler( HttpContext context, object data, ref HttpValidationStatus validationStatus )
            {
                validationStatus = OnCacheAuthorization( new HttpContextWrapper( context ) );
            }
    
            public override void OnAuthorization( AuthorizationContext filterContext )
            {
                if (filterContext == null)
                {
                    throw new ArgumentNullException( "filterContext" );
                }
    
                if (AuthorizeCore( filterContext.HttpContext ))
                {
                    SetCachePolicy( filterContext );
                }
                else if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
                {
                    // auth failed, redirect to login page
                    filterContext.Result = new HttpUnauthorizedResult();
                }
                else if (filterContext.HttpContext.User.IsInRole( "SuperUser" ))
                {
                    // is authenticated and is in the SuperUser role
                    SetCachePolicy( filterContext );
                }
                else
                {
                    ViewDataDictionary viewData = new ViewDataDictionary();
                    viewData.Add( "Message", "You do not have sufficient privileges for this operation." );
                    filterContext.Result = new ViewResult { MasterName = this.MasterName, ViewName = this.ViewName, ViewData = viewData };
                }
    
            }
    
            protected void SetCachePolicy( AuthorizationContext filterContext )
            {
                // ** IMPORTANT **
                // Since we're performing authorization at the action level, the authorization code runs
                // after the output caching module. In the worst case this could allow an authorized user
                // to cause the page to be cached, then an unauthorized user would later be served the
                // cached page. We work around this by telling proxies not to cache the sensitive page,
                // then we hook our custom authorization code into the caching mechanism so that we have
                // the final say on whether a page should be served from the cache.
                HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
                cachePolicy.SetProxyMaxAge( new TimeSpan( 0 ) );
                cachePolicy.AddValidationCallback( CacheValidateHandler, null /* data */);
            }
    
    
        }
    

    您可以在自定义的AuthorizeAttribute使用可重写的HandleUnauthorizedRequest

    喜欢这个:

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        // Returns HTTP 401 by default - see HttpUnauthorizedResult.cs.
        filterContext.Result = new RedirectToRouteResult(
        new RouteValueDictionary 
        {
            { "action", "YourActionName" },
            { "controller", "YourControllerName" },
            { "parameterName", "YourParameterValue" }
        });
    }
    

    你也可以做这样的事情:

    private class RedirectController : Controller
    {
        public ActionResult RedirectToSomewhere()
        {
            return RedirectToAction("Action", "Controller");
        }
    }
    

    现在你可以这样用你的HandleUnauthorizedRequest方法使用它:

    filterContext.Result = (new RedirectController()).RedirectToSomewhere();
    

    “tvanfosson”的代码给了我“错误执行子请求”..我已经改变了这样的OnAuthorization:

    public override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);
    
            if (!_isAuthorized)
            {
                filterContext.Result = new HttpUnauthorizedResult();
            }
            else if (filterContext.HttpContext.User.IsInRole("Administrator") || filterContext.HttpContext.User.IsInRole("User") ||  filterContext.HttpContext.User.IsInRole("Manager"))
            {
                // is authenticated and is in one of the roles 
                SetCachePolicy(filterContext);
            }
            else
            {
                filterContext.Controller.TempData.Add("RedirectReason", "You are not authorized to access this page.");
                filterContext.Result = new RedirectResult("~/Error");
            }
        }
    

    这很好,我在错误页面上显示TempData。 感谢代码片段的“tvanfosson”。 我正在使用Windows身份验证和_isAuthorized是什么,但HttpContext.User.Identity.IsAuthenticated ...

    链接地址: http://www.djcxy.com/p/30175.html

    上一篇: Redirecting unauthorized controller in ASP.NET MVC

    下一篇: XCode 7.1 Testflight Internal Testing bug