How do I create a custom AuthorizeAttribute that is specific to the area, controller and action?

后端 未结 3 660
忘了有多久
忘了有多久 2020-12-15 11:35

In other words, is this a really stupid idea?

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeActionAttribute : Auth         


        
3条回答
  •  旧时难觅i
    2020-12-15 12:24

    If you want to do this, taking Levi's recommendation into account, the answer is as follows:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Security;
    
    namespace MvcApplication1.Extension.Attribute
    {
        [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
        public class AuthorizeActionAttribute : AuthorizeAttribute
        {
            /// 
            /// Called when a process requests authorization.
            /// 
            /// The filter context, which encapsulates information for using .
            /// The  parameter is null.
            public override void OnAuthorization(AuthorizationContext filterContext)
            {
                if (filterContext == null)
                {
                    throw new ArgumentNullException("filterContext");
                }
    
                if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
                {
                    // auth failed, redirect to login page
                    filterContext.Result = new HttpUnauthorizedResult();
    
                    return;
                }
    
                // these values combined are our roleName
                string roleName = GetRoleName(filterContext);
    
                if (!filterContext.HttpContext.User.IsInRole(roleName))
                {
                    filterContext.Controller.TempData.Add("RedirectReason", "You are not authorized to access this page.");
                    filterContext.Result = new RedirectResult("~/Error/Unauthorized");
    
                    return;
                }
    
                //
                base.OnAuthorization(filterContext);
            }
    
            /// 
            /// Gets the name of the role. Theorectical construct that illustrates a problem with the
            /// area name. RouteData is apparently insecure, but the area name is available there.
            /// 
            /// The filter context.
            /// The version.
            /// 
            string GetRoleName(AuthorizationContext filterContext)
            {
                //
                var verb = filterContext.HttpContext.Request.HttpMethod;
    
                // recommended way to access controller and action names
                var controllerFullName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerType.FullName;
                var actionName = filterContext.ActionDescriptor.ActionName;
    
                return String.Format("{0}.{1}-{2}", controllerFullName, actionName, verb);
            }
        }
    }
    

    I did not want to provide a HttpUnauthorizedResult in the case of a user not being in role, because the result is to send the user to the login page. Considering that they are already logged in, this is extremely confusing to the user.

提交回复
热议问题