实体模型支持直接使用枚举类型
大石头 编写于 2017-08-08 18:24:40
X
using System;
using System.Web;
using System.Web.Mvc;
using NewLife.Log;
using XCode.Membership;

namespace NewLife.Cube
{
    /// <summary>实体授权特性</summary>
    public class EntityAuthorizeAttribute : AuthorizeAttribute
    {
        #region 属性
        /// <summary>资源名称。需要增加新菜单而不需要控制器名称时,指定资源名称</summary>
        public String ResourceName { get; set; }

        /// <summary>授权项</summary>
        public PermissionFlags Permission { get; set; }

        /// <summary>是否全局特性</summary>
        internal Boolean IsGlobal;
        #endregion

        #region 构造
        /// <summary>实例化实体授权特性</summary>
        public EntityAuthorizeAttribute() { }

        /// <summary>实例化实体授权特性</summary>
        /// <param name="permission"></param>
        public EntityAuthorizeAttribute(PermissionFlags permission = PermissionFlags.None)
        {
            //ResourceName = resourceName;
            Permission = permission;
        }
        #endregion

        #region 方法
        /// <summary>授权核心</summary>
        /// <param name="httpContext"></param>
        /// <returns></returns>
        protected override Boolean AuthorizeCore(HttpContextBase httpContext)
        {
            var user = httpContext.User?.Identity as IUser;
            return user != null;
        }

        /// <summary>授权发生时触发</summary>
        /// <param name="filterContext"></param>
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            // 只验证管辖范围
            if (!AreaRegistrationBase.Contains(filterContext.Controller)) return;

            ManageProvider.Provider.SetPrincipal();

            var act = filterContext.ActionDescriptor;

            // 如果控制器或者Action放有该特性,则跳过全局
            if (IsGlobal)
            {
                if (act.IsDefined(typeof(EntityAuthorizeAttribute), true) || act.ControllerDescriptor.IsDefined(typeof(EntityAuthorizeAttribute), true)) return;
            }

            // 允许匿名访问时,直接跳过检查
            if (act.IsDefined(typeof(AllowAnonymousAttribute), true) || act.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true)) return;

            // 判断当前登录用户
            var user = ManageProvider.User;
            if (user == null)
            {
                //HandleUnauthorizedRequest(filterContext);
                var ctx = filterContext.HttpContext;
                var rurl = HttpRuntime.AppDomainAppVirtualPath.EnsureEnd("/");
                rurl += "Admin/User/Login";
                if (ctx.Request.Url != null) rurl += "?returnUrl=" + ctx.Request.Url;

                filterContext.HttpContext.Response.Redirect(rurl, true);
                return;
            }

            // 根据请求Url定位资源菜单
            var url = filterContext.HttpContext.Request.AppRelativeCurrentExecutionFilePath;
            var menu = ManageProvider.Menu.Current;
            if (menu != null)
            {
                var role = user?.Role;
                if (role != null && role.Has(menu.ID, Permission)) return;
            }
            else
            {
                XTrace.WriteLine("设计错误!验证权限时无法找到[{0}]的菜单", url);
            }

            var res = "[{0}/{1}] {2}".F(act.ControllerDescriptor.ControllerName, act.ActionName, menu != null ? (menu + "") : url);
            var msg = "访问资源 {0} 需要 {1} 权限".F(res, Permission.GetDescription());
            LogProvider.Provider.WriteLog("访问", "拒绝", msg);

            var vr = new ViewResult()
            {
                ViewName = "NoPermission"
            };
            vr.ViewBag.Context = filterContext;
            vr.ViewBag.Resource = res;
            vr.ViewBag.Permission = Permission;

            filterContext.Result = vr;
        }
        #endregion
    }
}