我在ASP.NET MVC中有一个控制器,但仅限于管理员角色:
[Authorize(Roles = "Admin")] public class TestController : Controller { ...
如果没有管理员角色的用户导航到该控制器,则会看到空白屏幕。
我想做的就是将他们重定向到View,上面写着“您必须具有管理员角色才能访问此资源”。
我想到的一种方法是检查IsUserInRole()上的每个操作方法,如果不起作用,则返回此信息视图。但是,我必须将其放入每个会破坏DRY原理并且很麻烦维护的Action中。
创建基于AuthorizeAttribute的自定义授权属性,并覆盖OnAuthorization来执行检查操作的方式。通常,如果授权检查失败,则AuthorizeAttribute会将过滤结果设置为HttpUnauthorizedResult。您可以将其设置为(错误视图的)ViewResult。
编辑 :我有几个博客文章,将更详细地介绍:
例:
[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 */); } }