ASP.NET MVC Custom Authorization

前端 未结 3 714
孤城傲影
孤城傲影 2020-12-22 18:51

I have a question about custom authorization in MVC.

I have a site that I want to limit access to certain pages, depending on their group membership. Now I have see

3条回答
  •  -上瘾入骨i
    2020-12-22 19:20

    The AuthorizationContext (parameter to OnAuthorize) provides access to the Controller, RouteData, HttpContext, etc. You should be able to use these in a custom authorization filter to do what you want. Below is a sample of code from a RoleOrOwnerAttribute derived from AuthorizeAttribute.

    public override void OnAuthorization( AuthorizationContext filterContext )
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException( "filterContext" );
        }
    
        if (AuthorizeCore( filterContext.HttpContext )) // checks roles/users
        {
            SetCachePolicy( filterContext );
        }
        else if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            // auth failed, redirect to login page
            filterContext.Result = new HttpUnauthorizedResult();
        }
        // custom check for global role or ownership
        else if (filterContext.HttpContext.User.IsInRole( "SuperUser" ) || IsOwner( filterContext ))
        {
            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 };
        }
    
    }
    
    // helper method to determine ownership, uses factory to get data context,
    // then check the specified route parameter (property on the attribute)
    // corresponds to the id of the current user in the database.
    private bool IsOwner( AuthorizationContext filterContext )
    {
        using (IAuditableDataContextWrapper dc = this.ContextFactory.GetDataContextWrapper())
        {
            int id = -1;
            if (filterContext.RouteData.Values.ContainsKey( this.RouteParameter ))
            {
                id = Convert.ToInt32( filterContext.RouteData.Values[this.RouteParameter] );
            }
    
            string userName = filterContext.HttpContext.User.Identity.Name;
    
            return dc.Table().Where( p => p.UserName == userName && p.ParticipantID == id ).Any();
        }
    }
    
    
    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 */);
    }
    

提交回复
热议问题