ASP.NET经典权限解决方案,适用于OA、CRM、ERP、HR等应用系统

1 篇文章 0 订阅
1 篇文章 0 订阅

经典权限解决方案

1.权限简介
一般的管理系统都需要对用户的操作进行一定的限制,有的用户可以有许多操作,有的则有少量的操作.这样就需要一个授权机制,基于角色的授权机制描述了某个角色拥有一定数量的操作授权,属于该角色的用户则也就拥有了该角色的权限,且若用户属于多个角色则其拥有多个角色权限的集合.
我们的权限精确到按钮级别,如共享文档管理,管理可以查询、上传文档、下载文档、删除文档等操作,而一般的用户只需要查询和下载文档就可以了,
这时候我们的权限管理就发挥了作用, 下面让我们一步步开始实现!
我们使用ASP.NET结合jQuery、EasyUI实现一个精典的权限管理机制

2.数据模型设计
数据模型包括:员工表,角色表,员工与角色关系表和角色权限表
员工表: 员工登录到系统,如下图
这里写图片描述

角色表:授权权限的集合对象,如下图
这里写图片描述

角色表与员工关系表:如下图
这里写图片描述

角色权限表:如下图
这里写图片描述

3.Action定义
用户对应某功能的操作(如:增\删\改\查)需要一一建立相应操作行为实例(Action),这里以”文档管理”为例: 变量代表文档管理中的单个操作,例如 Directory_add = “j”;代表添加文档操作,其他各操作定义如下:

        public static string Directory_browse = "i";//文档浏览操作
        public static string Directory_add = "j";//文档浏览添加
        public static string Directory_update = "k";//文档浏览修改
        public static string Directory_delete = "l";//文档浏览删除

定义文档操作Action: 每个Action有标题(text)、图标(iconCls)、处理函数(handler),如下:

    /// <summary>
    /// 文档操作Action
    /// </summary>
    public class DocActions
    {
        public static ToolbarItem Query = new ToolbarItem()
        {
            text = "查询",
            iconCls = "icon-search",
            handler = "oa.os.doc.onBtnQueryDocClick"
        };
        public static ToolbarItem Refresh = new ToolbarItem()
        {
            text = "刷新",
            iconCls = "icon-reload",
            handler = "oa.os.doc.onBtnRefreshDocClick"
        };
        public static ToolbarItem Upload = new ToolbarItem()
        {
            text = "上传文档",
            iconCls = "icon-add",
            handler = "oa.os.doc.onBtnUploadDocClick"
        };
        public static ToolbarItem Update = new ToolbarItem()
        {
            text = "编辑",
            iconCls = "icon-application_edit",
            handler = "oa.os.doc.onBtnEditDocClick"
        };
        public static ToolbarItem Delete = new ToolbarItem()
        {
            text = "删除",
            iconCls = "icon-delete",
            handler = "oa.os.doc.onBtnDelDocClick"
        };
    }

4.给角色授权, 结合EasyUI数据表格组件,效果如下图
这里写图片描述

勾选复选框就表示为该角色授权其他的操作

权限目录树的初始化,如下(在AppPermission.cs类)

        /// <summary>
        /// 初始化权限目录树
        /// </summary>
        /// <returns></returns>
        private static PermTreeNode[] CreatePermission()
        {
            PermTreeNode[] nodes = new PermTreeNode[]{
                new PermTreeNode() { 
                    Name = "系统权限",Id="",
                    children = new PermTreeNode[]{
                        new PermTreeNode()
                        {                  
                            Name = "个人办公",
                            children=new PermTreeNode[]{
                                new PermTreeNode()
                                {
                                    Name = "个人考勤",
                                    Action1 = new PermAction() { Name = "个人考勤管理", Action = AppAction.PunchInOut }
                                },                                                                
                                new PermTreeNode()
                                {
                                    Name = "工作日志",
                                    Action1 = new PermAction() { Name = "工作日志管理", Action = AppAction.WorkLog }
                                }
                            }
                        },
                        new PermTreeNode()
                        {                  
                            Name = "人事管理",
                            children=new PermTreeNode[]{
                                new PermTreeNode()
                                {
                                    Name = "部门管理",
                                    Action1 = new PermAction() { Name = "添加", Action = AppAction.Department_add },
                                    Action2 = new PermAction() { Name = "编辑", Action = AppAction.Department_update },
                                    Action3 = new PermAction() { Name = "删除", Action = AppAction.Department_delete }
                                },                                                                
                                new PermTreeNode()
                                {
                                    Name = "员工管理",
                                    Action1 = new PermAction() { Name = "浏览", Action = AppAction.Employee_browse },
                                    Action2 = new PermAction() { Name = "添加", Action = AppAction.Employee_add },
                                    Action3 = new PermAction() { Name = "编辑", Action = AppAction.Employee_update },
                                    Action4 = new PermAction() { Name = "删除", Action = AppAction.Employee_delete }
                                }
                            }
                        },
                        new PermTreeNode()
                        {                  
                            Name = "文档管理",
                            children=new PermTreeNode[]{
                                new PermTreeNode()
                                {
                                    Name = "目录管理",
                                    Action1 = new PermAction() { Name = "添加", Action = AppAction.Directory_add },
                                    Action2 = new PermAction() { Name = "编辑", Action = AppAction.Directory_update },
                                    Action3 = new PermAction() { Name = "删除", Action = AppAction.Directory_delete }
                                },                                                                
                                new PermTreeNode()
                                {
                                    Name = "文档管理",
                                    Action1 = new PermAction() { Name = "浏览", Action = AppAction.Document_browse },
                                    Action2 = new PermAction() { Name = "添加", Action = AppAction.Document_add },
                                    Action3 = new PermAction() { Name = "编辑", Action = AppAction.Document_update },
                                    Action4 = new PermAction() { Name = "删除", Action = AppAction.Document_delete }
                                }
                            }
                        },
                        //系统管理
                        new PermTreeNode()
                        {
                            Name = "系统管理",
                            children=new PermTreeNode[]{
                                new PermTreeNode()
                                {
                                    Name = "角色管理",
                                    Action1 = new PermAction() { Name = "浏览", Action = AppAction.Role_browse },
                                    Action2 = new PermAction() { Name = "添加", Action = AppAction.Role_add },
                                    Action3 = new PermAction() { Name = "编辑", Action = AppAction.Role_update },
                                    Action4 = new PermAction() { Name = "删除", Action = AppAction.Role_delete }
                                },
                                new PermTreeNode()
                                {
                                    Name = "操作日志管理",
                                    Action1 = new PermAction() { Name = "浏览", Action = AppAction.OperatLog }
                                }
                            }                                
                        }
                    }
                }   
            };

            InitSystemPerm(nodes);
            return nodes;
        }

Role.js加载角色列表,如下

    f.prototype.queryRole=function(toolbar){
        $(datagridId).datagrid({
            url:'Handler/RoleHandler.ashx?Action=GetRoles',
            idField:'Id',
            rownumbers:true,
            singleSelect:true,
            checkOnSelect:false,
            selectOnCheck:false,
            pagination:true,
            pageSize:20,fitColumns:true,
            sortName:'Name',
            //onClickRow:onClickRow,
            onClickCell: onClickCell,
            onAfterEdit: onAfterEdit,            
            view: detailview,
            toolbar:toolbar,
            columns:[[
                {field:'ck',checkbox:true},
                {
                    title:'角色名称',field:'Name',sortable:true,width:150,
                    formatter:function(value, row, index){
                        return value && value.length > 8 ? '<span title="' + value + '">' + value + '</span>' : value;
                    },
                    editor:{type:'textbox',options:{required:true,missingMessage:'请输入角色名称'}}
                },
                {
                    title:'角色描述',field:'Remark',sortable:true,width:800,
                    formatter:function(value, row, index){
                        return value && value.length > 20 ? '<span title="' + value + '">' + value + '</span>' : value;
                    },
                    editor:'textbox'
                }
            ]],
            detailFormatter:function(index,row){
                //return '<div style="padding:2px"><ul class="ddv"></ul></div>';
                return '<div style="padding:2px"><table class="ddv"></table></div>';
            },
            onExpandRow: function(index,row){
                var roleIndex=index;
                var roleId=row.Id;
                var ddv = $(this).datagrid('getRowDetail',index).find('table.ddv');
                ddv.treegrid({    
                    url:'Handler/AuthorHandler.ashx?Action=GetRolePerms&RoleId='+row.Id,    
                    idField:'Id',    
                    treeField:'Name',  
                    lines:true,  
                    columns:[[    
                        {title:'系统权限设置',field:'Name',width:200,
                            formatter: function(value,row,index){
                                return '<input type="checkbox" roleId='+roleId+' permId='+row.Id+' roleindex="'+roleIndex+'" path="'+row.Path+'" '+row.Checked+' onclick="oa.os.perm.onNodeCheckboxClick(this)" />'+value;
                            }
                        },    
                        {field:'Action1',title:'',width:100,
                            formatter: function(value,row,index){
                                if(value && value.Name){
                                    return '<input type="checkbox" roleId='+roleId+' action='+value.Action+' roleindex="'+roleIndex+'" path="'+row.Path+'" '+value.Checked+' onclick="oa.os.perm.onCheckboxClick(this)" />'+value.Name;
                                }
                            }
                        },
                        {field:'Action2',title:'',width:100,
                            formatter: function(value,row,index){
                                if(value && value.Name){
                                    return '<input type="checkbox" roleId='+roleId+' action='+value.Action+' roleindex="'+roleIndex+'" path="'+row.Path+'" '+value.Checked+' onclick="oa.os.perm.onCheckboxClick(this)" />'+value.Name;
                                }
                            }
                        },
                        {field:'Action3',title:'',width:100,
                            formatter: function(value,row,index){
                                if(value && value.Name){
                                    return '<input type="checkbox" roleId='+roleId+' action='+value.Action+' roleindex="'+roleIndex+'" path="'+row.Path+'" '+value.Checked+' onclick="oa.os.perm.onCheckboxClick(this)" />'+value.Name;
                                }
                            }
                        },
                        {field:'Action4',title:'',width:100,
                            formatter: function(value,row,index){
                                if(value && value.Name){
                                    return '<input type="checkbox" roleId='+roleId+' action='+value.Action+' roleindex="'+roleIndex+'" path="'+row.Path+'" '+value.Checked+' onclick="oa.os.perm.onCheckboxClick(this)" />'+value.Name;
                                }
                            }
                        },
                        {field:'Action5',title:'',width:100,
                            formatter: function(value,row,index){
                                if(value && value.Name){
                                    return '<input type="checkbox" roleId='+roleId+' action='+value.Action+' roleindex="'+roleIndex+'" path="'+row.Path+'" '+value.Checked+' onclick="oa.os.perm.onCheckboxClick(this)" />'+value.Name;
                                }
                            }
                        },
                        {field:'Action6',title:'',width:100,
                            formatter: function(value,row,index){
                                if(value && value.Name){
                                    return '<input type="checkbox" roleId='+roleId+' action='+value.Action+' roleindex="'+roleIndex+'" path="'+row.Path+'" '+value.Checked+' onclick="oa.os.perm.onCheckboxClick(this)" />'+value.Name;
                                }
                            }
                        },
                        {field:'Action7',title:'',width:100,
                            formatter: function(value,row,index){
                                if(value && value.Name){
                                    return '<input type="checkbox" roleId='+roleId+' action='+value.Action+' roleindex="'+roleIndex+'" path="'+row.Path+'" '+value.Checked+' onclick="oa.os.perm.onCheckboxClick(this)" />'+value.Name;
                                }
                            }
                        },
                        {field:'Action8',title:'',width:100,
                            formatter: function(value,row,index){
                                if(value && value.Name){
                                    return '<input type="checkbox" roleId='+roleId+' action='+value.Action+' roleindex="'+roleIndex+'" path="'+row.Path+'" '+value.Checked+' onclick="oa.os.perm.onCheckboxClick(this)" />'+value.Name;
                                }
                            }
                        },
                        {field:'Action9',title:'',width:100,
                            formatter: function(value,row,index){
                                if(value && value.Name){
                                    return '<input type="checkbox" roleId='+roleId+' action='+value.Action+' roleindex="'+roleIndex+'" path="'+row.Path+'" '+value.Checked+' onclick="oa.os.perm.onCheckboxClick(this)" />'+value.Name;
                                }
                            }
                        },
                        {field:'Action10',title:'',width:100,
                            formatter: function(value,row,index){
                                if(value && value.Name){
                                    return '<input type="checkbox" roleId='+roleId+' action='+value.Action+' roleindex="'+roleIndex+'" path="'+row.Path+'" '+value.Checked+' onclick="oa.os.perm.onCheckboxClick(this)" />'+value.Name;
                                }
                            }
                        }
                    ]] ,
                    onResize:function(){
                        $(datagridId).datagrid('fixDetailRowHeight',index);
                    },
                    onCollapse:function(row){
                        $(datagridId).datagrid('fixDetailRowHeight',index);
                    },
                    onExpand:function(row){
                        $(datagridId).datagrid('fixDetailRowHeight',index);
                    },
                    onLoadSuccess:function(){
                        setTimeout(function(){
                            $(datagridId).datagrid('fixDetailRowHeight',index);
                        },0);
                    }
                }); 
                $(datagridId).datagrid('fixDetailRowHeight',index);
            }
        });
    };

勾选/去掉勾选相应的操作复选框以保存该角色的该操作权限:
JS:

var saveRolePermAction=function(roleId,action,checked,fn){
        $.ajax({
            url: "Handler/AuthorHandler.ashx",
            data: {Action:'SaveRolePermAction',RoleId:roleId,Actions:action,Checked:checked},
            type: "get",
            dataType: "json",
            success: function (data) {
                if (data.success) {
                    if(fn){
                        fn();
                    }
                }else{
                    $.messager.alert("错误",data.msg,"error");
                }
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                if (textStatus == "timeout") {
                    $.messager.alert("提示", "请求超时,请刷新当前页重试!");
                }
                else {
                    $.messager.alert("错误", textStatus + ":" + errorThrown);
                }
            }
        });
    };

AuthorHandler.ashx.cs :

public string SaveRolePermAction(HttpRequest request)
        {
            string response = string.Empty;
            try
            {
                SaveRolePermActionRequestParam param = RequestParamHandler.GetParam<SaveRolePermActionRequestParam>(request);
                bool flag = AuthorController.SaveRolePermissionAction(param.RoleId, param.Actions, param.Checked);
                if (flag)
                {
                    response = "{\"success\":true,\"msg\":\"保存成功\"}";
                }
                else
                {
                    response = "{\"success\":false,\"msg\":\"保存失败!\"}";
                }
            }
            catch (RequestParamException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                throw;
            }
            return response;
        }

AuthorController.cs :

/// <summary>
        /// 保存指定角色指定操作的授权
        /// </summary>
        /// <param name="roleId"></param>
        /// <param name="action"></param>
        /// <param name="check"></param>
        /// <returns></returns>
        public static bool SaveRolePermissionAction(int roleId, string action, bool check)
        {
            return SaveRolePermission(roleId, new string[] { action }, check);
        }

        /// <summary>
        /// 保存指定角色指定操作的授权
        /// </summary>
        /// <param name="roleId"></param>
        /// <param name="actions"></param>
        /// <param name="check"></param>
        /// <returns></returns>
        private static bool SaveRolePermission(int roleId, string[] actions, bool check)
        {
            return Permission.SaveRolePermission(roleId, actions, check);
        }

OA.BLL.Permission.cs :

/// <summary>
        /// 保存角色权限
        /// </summary>
        /// <param name="roleId"></param>
        /// <param name="actions"></param>
        /// <param name="isChecked"></param>
        /// <returns></returns>
        public static bool SaveRolePermission(int roleId, string[] actions, bool isChecked)
        {
            return dal.SaveRolePermission(roleId, actions, isChecked);
        }

OA.SQLServerDAL.Permission.cs :

        /// <summary>
        /// 保存角色权限
        /// </summary>
        /// <param name="roleId"></param>
        /// <param name="actions"></param>
        /// <param name="isChecked"></param>
        /// <returns></returns>
        public bool SaveRolePermission(int roleId, string[] actions, bool isChecked)
        {
            StringBuilder sql = new StringBuilder();
            if (isChecked)
            {
                if (actions.Length > 0)
                {
                    ArrayList sqlList = new ArrayList();
                    IList<DbParameter[]> parmList = new List<DbParameter[]>();
                    SqlParameter[] parm = new SqlParameter[1];
                    foreach (string item in actions)
                    {
                        parm = new SqlParameter[2];
                        parm[0] = new SqlParameter("@RoleId", SqlDbType.Int);
                        parm[0].Value = roleId;
                        parm[1] = new SqlParameter("@Action", SqlDbType.VarChar, 64);
                        parm[1].Value = SQLHelper.Escape(item);

                        sqlList.Add("proc_PermissionOfRoleInsert");
                        parmList.Add(parm);
                    }
                    SQLHelper.ExecuteTranByProcedure(sqlList, parmList);
                }
            }
            else
            {
                string actionStr = SQLHelper.ConverArrayToStringArray(actions);
                sql.Append("delete from RolePermission where RoleId='").Append(roleId).Append("' and Action in(").Append(actionStr).Append(")");
                SQLHelper.Update(sql.ToString());
            }
            return true;
        }
    }

存储过程: proc_PermissionOfRoleInsert

--创建添加角色权限存储过程
if exists(select * from sysobjects where type='p' and name='proc_PermissionOfRoleInsert')
begin
    drop procedure proc_PermissionOfRoleInsert  
end
go
create procedure proc_PermissionOfRoleInsert
(
    @RoleId int,
    @Action varchar(64)
)
as
    declare @e int
    set @e=0;
    select @e=1 from RolePermission where RoleId=@RoleId and Action=@Action;
    if(@e<1)
    begin
        insert RolePermission(RoleId,[Action],[Option]) values(@RoleId,@Action,1);
    end
go

保存结果如下图 :
这里写图片描述

5.新建员工,并为员工分配角色,如下图:
这里写图片描述

6.员工登录: 登录后获取员工基本信息和授权信息等保存在Cookie中,以后员工的每次操作都从Cookie中获取授权信息并以AOP方式进行权限验证,没有授权的操作以抛出权限异常的方式终止操作,以保护数据的安全
登录:
这里写图片描述

登录请求AuthHandler.ashx.cs

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private string SingIn(HttpRequest request)
        {
            AuthResponseParm resp = new AuthResponseParm();
            string response = string.Empty;
            try
            {
                AuthParm param = RequestParamHandler.GetParam<AuthParm>(request);
                IList<string> roles = null;
                IList<PermissionInfo> perms = null;
                EmployeeInfo employeeInfo = AuthController.Validate(param.UserName, param.Password, out roles, out perms);
                if (null != employeeInfo)
                {
                    resp.Flag = 1;

                    UserPrincipal userinfo = new UserPrincipal();
                    userinfo.UserId = employeeInfo.Id.ToString();
                    userinfo.UserName = param.UserName;
                    userinfo.Roles = roles;
                    if (null != perms && perms.Count > 0)
                    {
                        //userinfo.PermissionList = perms;
                        userinfo.Permissions = ConvertPermissionsToJson(perms.ToArray<PermissionInfo>());// new AuthorizationController().ConvertPermissionsToJson(parm.UserName);
                    }
                    // 登录状态1天或者7天内有效
                    int validDays = param.Valid7 ? 7 : 1;
                    FormsPrincipal<UserPrincipal>.SavePrincipalToCookie("Login", userinfo, validDays * 24 * 60);
                }
                else
                {
                    resp.Flag = 0;
                    resp.Msg = "用户名和密码错误,请重新输入.";
                }
            }
            catch (Exception ex)
            {
                resp.Flag = 0;
            }
            response = JsonHelper.JsonSerializer<AuthResponseParm>(resp);
            return response;
        }

其中 EmployeeInfo employeeInfo = AuthController.Validate(param.UserName, param.Password, out roles, out perms); 进行员工名和密码验证,并且返回该员工的授权信息

保存员工基本信息和授权信息在Cookie中:

        /// <summary>
        /// 保存用户信息到Cookie
        /// </summary>
        /// <param name="loginName">登录名</param>
        /// <param name="userData">与登录名相关的用户信息</param>
        /// <param name="expiration">登录Cookie的过期时间,单位:分钟。</param>
        public static void SavePrincipalToCookie(string loginName, TUserData userData, int expiration)
        {
            if (string.IsNullOrEmpty(loginName))
                throw new ArgumentNullException("loginName");
            if (userData == null)
                throw new ArgumentNullException("userData");

            // 1. 把需要保存的用户数据转成一个字符串。
            string data = null;
            if (userData != null)
                data = (new JavaScriptSerializer()).Serialize(userData);


            // 2. 创建一个FormsAuthenticationTicket,它包含登录名以及额外的用户数据。
            FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
                2, loginName, DateTime.Now, DateTime.Now.AddDays(1), true, data);


            // 3. 加密Ticket,变成一个加密的字符串。
            string cookieValue = FormsAuthentication.Encrypt(ticket);


            // 4. 根据加密结果创建登录Cookie
            HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, cookieValue);
            cookie.HttpOnly = true;
            cookie.Secure = FormsAuthentication.RequireSSL;
            cookie.Domain = FormsAuthentication.CookieDomain;
            cookie.Path = FormsAuthentication.FormsCookiePath;
            if (expiration > 0)
                cookie.Expires = DateTime.Now.AddMinutes(expiration);

            HttpContext context = HttpContext.Current;
            if (context == null)
                throw new InvalidOperationException();

            // 5. 写登录Cookie
            context.Response.Cookies.Remove(cookie.Name);
            context.Response.Cookies.Add(cookie);
        }

7.以文档管理为例讲解员工的授权,页面如下图
这里写图片描述

新建文档管理index.html页面

<script src="Scripts/OS/Doc/Doc.js" type="text/javascript"></script>
<div class="easyui-layout" data-options="fit:true">
    <div data-options="region:'west',split:true,title:'地址导航'" style="width: 280px; padding: 0;border-left:0; border-bottom:0; border-top:0;">
        <div class="easyui-layout" data-options="fit:true">
            <div data-options="region:'north'" id="dirActionMbContain_doc" style="height:28px;border-top:0;border-left:0;border-right:0;">
                <a href="#" class="easyui-linkbutton" data-options="plain:true,iconCls:'icon-arrow_out',onClick:oa.os.doc.expandAll"></a>
                <a href="#" class="easyui-linkbutton" data-options="plain:true,iconCls:'icon-arrow_in',onClick:oa.os.doc.collapseAll"></a>
                <a href="#" class="easyui-linkbutton" data-options="plain:true,iconCls:'icon-arrow_refresh',onClick:oa.os.doc.reloadDirTree"></a>
            </div>
            <div data-options="region:'center',border:false">
                <ul id="tree_dir_doc">
                </ul>
            </div>
        </div>
    </div>
    <div data-options="region:'center'" style=" border-bottom:0; border-top:0;border-right:0;">
        <div id="tabs_doc_doc" class="easyui-tabs" data-options="fit:true,border:false">
            <div title="文档列表" data-options="iconCls:'icon-layout_sidebar'">
                <table id="grid_doc_doc" data-options="fit:true,border:false">
                </table>
            </div>
        </div>
    </div>
</div>
<div id="dirMenuButton_doc" style="width:150px;"></div>
<div id="dirContextMenu_doc" class="easyui-menu" style="width:150px;"></div>
<div id="toolbar_docDatagrid_doc" style="padding:3px;height:auto">
    文档名称: <input id="toolbar_name_docDatagrid_doc" class="easyui-textbox" data-options="" style="width:120px">
</div>

新建Global.asax

        /// <summary>
        /// http请求时从Cookie获取用户基本信息和授权信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Application_AuthenticateRequest(object sender, EventArgs e)
        {
            HttpApplication app = (HttpApplication)sender;
            FormsPrincipal<UserPrincipal>.TrySetUserInfo(app.Context);
        }

FormsPrincipal.cs

        /// <summary>
        /// 根据HttpContext对象设置用户标识对象
        /// </summary>
        /// <param name="context"></param>
        public static void TrySetUserInfo(HttpContext context)
        {
            if (context == null)
                throw new ArgumentNullException("context");

            FormsPrincipal<TUserData> user = TryParsePrincipal(context.Request);
            if (user != null)
                context.User = user;
        }

新建Doc.js文件:

    //获取用户授权的文档的操作按钮列表
    function loadDocDatagridActions(callback){
        $.ajax({
            url: "Handler/AuthorHandler.ashx",
            data: {Action:'GetDocActions'},
            type: "get",
            dataType: "json",
            success: function (data) {
                createDocDatagridToolbar(data);
                callback();
            }
        });
    };  

AuthorHandler.cs

    /// <summary>
      /// 获取用户授权的文档的操作按钮列表
      /// </summary>
      /// <param name="request"></param>
      /// <returns></returns>
      public string GetDocActions(HttpRequest request)
      {
          string response = "[]";
          try
          {
              ToolbarItem[] items = AuthorController.GetDocActions();
              return ParseToolbarToJson(items);
          }
          catch (RequestParamException ex)
          {
              throw ex;
          }
          catch (Exception ex)
          {
              throw;
          }
          return response;
      }

AuthorController.cs,如下

        /// <summary>
        /// 获取指定用户授权的文档的操作按钮列表
        /// </summary>
        /// <returns></returns>
        public static ToolbarItem[] GetDocActions()
        {
            FormsPrincipal<UserPrincipal> user = Authen.GetUser();
            if (null != user && !string.IsNullOrEmpty(user.UserData.Permissions))
            {
                string permStr = user.UserData.Permissions;
                IList<ToolbarItem> items = new List<ToolbarItem>();
                if (AppAction.IsEnableDocumentBrowse(permStr))
                {
                    items.Add(DocActions.Query);
                }
                if (AppAction.IsEnableDocumentAdd(permStr))
                {
                    items.Add(DocActions.Upload);
                }
                if (AppAction.IsEnableDocumentUpdate(permStr))
                {
                    items.Add(DocActions.Update);
                }
                if (AppAction.IsEnableDocumentBrowse(permStr))
                {
                    items.Add(DocActions.Refresh);
                }
                return items.ToArray();
            }
            return null;
        }

AppAction.cs 如下

    #region 判断文档操作权限
        /// <summary>
        /// 是否有文档浏览权限
        /// </summary>
        /// <param name="permissions"></param>
        /// <returns></returns>
        public static bool IsEnableDocumentBrowse(string permissions)
        {
            return EnableAction(permissions, Document_browse) || IsEnableDocumentAdd(permissions)
            || IsEnableDocumentUpdate(permissions) || IsEnableDocumentDelete(permissions);
        }
        /// <summary>
        /// 是否有添加文档的权限
        /// </summary>
        /// <param name="permissions"></param>
        /// <returns></returns>
        public static bool IsEnableDocumentAdd(string permissions)
        {
            return EnableAction(permissions, Document_add);
        }
        /// <summary>
        /// 是否有更新文档的权限
        /// </summary>
        /// <param name="permissions"></param>
        /// <returns></returns>
        public static bool IsEnableDocumentUpdate(string permissions)
        {
            return EnableAction(permissions, Document_update);
        }
        /// <summary>
        /// 是否有删除文档的权限
        /// </summary>
        /// <param name="permissions"></param>
        /// <returns></returns>
        public static bool IsEnableDocumentDelete(string permissions)
        {
            return EnableAction(permissions, Document_delete);
        }
    #endregion

得到文档操作的Action列表后,Doc.js创建文档列表Datagrid工具栏

    //创建文档列表Datagrid工具栏
    function createDocDatagridToolbar(toolbar){
        $(datagridId).datagrid({ toolbar: '#toolbar_docDatagrid_doc'});
        $(datagridId).datagrid("addToolbarItem",toolbar);
    }

jquery.easyui.extension.js 用以添加工具栏按钮

//扩展datagrid增加工具按键
$.extend($.fn.datagrid.methods, {
    addToolbarItem: function (jq, items) {
        return jq.each(function () {
            var toolbar = $(this).parent().prev("div.datagrid-toolbar");
            for (var i = 0; i < items.length; i++) {
                var item = items[i];
                if (item === "-") {
                    toolbar.append('<div class="datagrid-btn-separator"></div>');
                } else {
                    var btn = $("<a href=\"javascript:void(0)\"></a>");
                    btn[0].onclick = eval(item.handler || function () { });
                    btn.appendTo(toolbar).linkbutton($.extend({}, item, { plain: true }));
                    //btn.css("float", "left").appendTo(toolbar).linkbutton($.extend({}, item, { plain: true }));
                }
            }
            toolbar = null;
        });
    },
    removeToolbarItem: function (jq, param) {
        return jq.each(function () {
            var btns = $(this).parent().prev("div.datagrid-toolbar").children("a");
            var cbtn = null;
            if (typeof param == "number") {
                cbtn = btns.eq(param);
            } else if (typeof param == "string") {
                var text = null;
                btns.each(function () {
                    text = $(this).data().linkbutton.options.text;
                    if (text == param) {
                        cbtn = $(this);
                        text = null;
                        return;
                    }
                });
            }
            if (cbtn) {
                var prev = cbtn.prev()[0];
                var next = cbtn.next()[0];
                if (prev && next && prev.nodeName == "DIV" && prev.nodeName == next.nodeName) {
                    $(prev).remove();
                } else if (next && next.nodeName == "DIV") {
                    $(next).remove();
                } else if (prev && prev.nodeName == "DIV") {
                    $(prev).remove();
                }
                cbtn.remove();
                cbtn = null;
            }
        });
    }
});
//用法:
//$('#tt').datagrid("addToolbarItem",[{"text":"xxx"},"-",{"text":"xxxsss","iconCls":"icon-ok"}]);

最终得到时授权的操作工具栏,如下图
这里写图片描述

如上图员工拥有对文档进行查询,添加,编辑和删除的授权操作,但是ajax发起的请求是可以伪造数据的,这就要在服务端再次对员工的授权进行验证, 此时利用AOP方式进行验证,也就是在进入真正的业务方法之前先进行授权验证,若没有权限则以抛出异常的方式终止后续操作

新建 DocCallHandler.cs, DocCallHandlerAttribute.cs和DocCallHandlerProperty.cs

/// <summary>
    /// 文档的web请求AOP
    /// </summary>
    public class DocCallHandler : CallHandlerBase
    {
        public DocCallHandler(IMessageSink nextSink)
            : base(nextSink)
        {
        }

        protected override void AddAllBeforeAOPHandles()
        {
            AddBeforeAOPHandle("ProcessRequest".ToUpper(), new BeforeAOPHandle(Before_Monitor));
        }
        protected override void AddAllAfterAOPHandles()
        {
            AddAfterAOPHandle("ProcessRequest".ToUpper(), new AfterAOPHandle(After_Monitor));
        }

        /// <summary>
        /// 在业务处理之前调用
        /// </summary>
        /// <param name="callMsg"></param>
        private void Before_Monitor(IMethodCallMessage callMsg)
        {
            if (null != callMsg)
            {
                HttpContext context = callMsg.Args[0] as HttpContext;
                string action = context.Request.Params["Action"];
                if (StringTools.MatchesStringIgnoreCase(action, "QueryDocsByDirId") || StringTools.MatchesStringIgnoreCase(action, "QueryDocsByName")
                    || StringTools.MatchesStringIgnoreCase(action, "QueryDocs") || StringTools.MatchesStringIgnoreCase(action, "QueryDocById")
                    || StringTools.MatchesStringIgnoreCase(action, "Download"))
                {
                    IsEnable(AppAction.IsEnableDocumentBrowse);
                }
                else if (StringTools.MatchesStringIgnoreCase(action, "AddDoc"))
                {
                    IsEnable(AppAction.IsEnableDocumentAdd);
                }
                else if (StringTools.MatchesStringIgnoreCase(action, "UpdateDoc"))
                {
                    IsEnable(AppAction.IsEnableDocumentUpdate);
                }
                else if (StringTools.MatchesStringIgnoreCase(action, "DeleteDoc"))
                {
                    IsEnable(AppAction.IsEnableDocumentDelete);
                }
            }
        }

        /// <summary>
        /// 在业务处理之后调用
        /// </summary>
        /// <param name="replyMsg"></param>
        private void After_Monitor(IMethodReturnMessage replyMsg)
        {
            if (null != replyMsg)
            {
                HttpContext context = replyMsg.Args[0] as HttpContext;
                string action = context.Request.Params["Action"];
                if (StringTools.MatchesStringIgnoreCase(action, "Download"))
                {
                    int id = RequestParamHandler.GetIntParam(context.Request, "Id");
                    SaveOperatLog("下载文档", "Id=" + id);
                }
                else if (StringTools.MatchesStringIgnoreCase(action, "AddDoc"))
                {
                    DocInfo doc = RequestParamHandler.GetParam<DocInfo>(context.Request, "Doc");
                    SaveOperatLog("添加文档", doc.ToString());
                }
                else if (StringTools.MatchesStringIgnoreCase(action, "UpdateDoc"))
                {
                    DocInfo doc = RequestParamHandler.GetParam<DocInfo>(context.Request, "Doc");
                    SaveOperatLog("更新文档", doc.ToString());
                }
                else if (StringTools.MatchesStringIgnoreCase(action, "DeleteDoc"))
                {
                    int id = RequestParamHandler.GetIntParam(context.Request, "Id");
                    SaveOperatLog("删除文档", "Id=" + id);
                }
            }
        }
    }

    [AttributeUsage(AttributeTargets.Class)]
    public class DocCallHandlerAttribute : AOPAttribute
    {
        protected override AOPProperty GetAOPProperty()
        {
            return new DocCallHandlerProperty();
        }
    }

    public class DocCallHandlerProperty : AOPProperty
    {
        protected override IMessageSink CreateSink(IMessageSink nextSink)
        {
            return new DocCallHandler(nextSink);
        }

        protected override string GetName()
        {
            return "";
        }
    }

并且在DocHandler.ashx.cs加上属性[DocCallHandler],如下

    /// <summary>
    /// 文档--web处理入口
    /// </summary>
    [DocCallHandler]
    public class DocHandler : HandlerBase, IHttpHandler, System.Web.SessionState.IRequiresSessionState
    {
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            string response = string.Empty;
            if (MatchesAction(context.Request.Params["Action"], "QueryDocsByDirId"))
            {

如员工添加文档时,

    else if (StringTools.MatchesStringIgnoreCase(action, "AddDoc"))
    {
        IsEnable(AppAction.IsEnableDocumentAdd);
    }

判断是否授权

       /// <summary>
        /// 判断是否授权
        /// </summary>
        /// <param name="validate"></param>
        protected void IsEnable(Validate validate)
        {
            FormsPrincipal<UserPrincipal> user = AuthController.GetUser();
            if (!validate(user.UserData.Permissions))
            {
                throw new NotPermissionException("");//抛出未授权异常
            }

若未授权该员工添加文档,则抛出未授权异常, Global.asax接收该异常

        /// <summary>
        /// 应用程序异常
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Application_Error(object sender, EventArgs e)
        {
            Exception objException = Server.GetLastError().GetBaseException();
            if (objException is NotPermissionException)
            {
                HttpContext.Current.Response.Write("{\"success\":false, \"msg\":\"无权限的操作.\"}");
            }
            else if (objException is NotLoginException)
            {
                HttpContext.Current.Response.Write("{\"success\":false, \"msg\":\"用户未登录.\"}");
            }
            else
            {
                HttpContext.Current.Response.Write("{\"success\":false, \"msg\":\"系统错误.\"}");
            }
            LogError();
            Server.ClearError();
        }

再以jsono数据格式返回响应结果,javascript再显示操作结果,如不图
这里写图片描述

代码下载1

代码下载2

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FrameWork权限管理 v1.0.8源码 源码描述: 其主要的功能就是,进行后台管理模块整合. 1)其可以支持多个应用,多个模块的权限管理. 2)支持Access和MsSql200/2005及Oracle9i以上. 3)采用角色来进行权限的授权,每个用户可以属于多个角色,享有交差权限. 4)整合方便,权限检测采用httpmodule方式检测.基本不用对原有程序进行修改,便可将原有程序进行整合. 5)可视化编辑,全新的Menu和Tab控件.支持拖拉式编辑. 6)统一的事件日志管理,所有登陆操作都有安全记录. 7)每个模块的每个栏目对应一个目录, 栏目的权限抽象分为(查看/新增/修改/删除/排序/打印/备用A/备用 8).目录里有一个web.config来进行目录文件权限配置,可直接将某个文件名设定到相对应的权限上. v1.0.8版更新记录 1.增加树状菜单样式,以适应多分类. 2.“查询”功能的地方,如果第一次查询后进行过翻页操作,再进行第二次的查询结果会停留在之前的页码处 3.Url地址权限判断,需要做长度对比.如设置defautl.aspx?cmd=122 则会自动匹配 defautl.aspx?cmd=122xxxxxxx 4.修改模块分类,提示请输入权限名称,其内容不可以为空 5.插入在线人员出错,重复值InsertOnlineUser 6.应用字段增加后,应用名称为输入框. 7.sys_FieldValueFromKey sys_FieldValueList 方法,排序为顺序acs 8.增加对应用的排序 9.增加操作日志删除和导出 10.date.js控件,选中当前日期返回值出错 11.登陆时,如已经登陆用户,点确认后直接登陆,不要让用户再重新输入用户名和密码 12.http://www.supesoft.com/bbs/disp.asp?B_T_ID=1313 13.修改默认同一ip登陆时出错次数为20次就禁止此ip登陆60分钟. 14.用户资料管理员,管理员只能管理自己部门下的用户(修改/删除) 15.后台增加禁止登陆ip限制.
1、菜单导航管理 2、操作按钮 3、角色管理 4、部门管理 5、用户管理(用户权限) 6、用户组管理(设置成员,用户组权限) 7、系统配置(动态配置系统参数) 8、附加属性(自定义属性) 9、系统日志(异常记录) 10、数据库备份/还原 11、资源管理,(动态数据库) 12、个人信息(基本信息,附加信息,用户角色,拥有权限) 13、首页快捷 14、数据回收站(业务功能删除过数据,全部保留在回收站) 15、系统个性化设置(切换菜单导航) 系统UI,给人感觉非常好,体积小巧,速度快 该源码是适用用于应用系统后台模块的管理(可扩展至支持集中化的权限管理平台), 0.支持N级菜单导航,菜单显示方式支持目前支持2种模式分别:菜单(无限级),横向(2级) 1.动态切换皮肤,目前有两狂UI 蓝色,咖啡色 2.表单验证,文本框高亮起来 3.可以动态分配权限按钮,分配角色权限,目录结构,栏目的链接都可以修改。权限管理非常灵活, 4.可以隐藏左侧导航栏,打开左侧导航栏,默认是打开,table表格都自应大小的 5.动态创建数据表,删除用户表,点击数据 表 可以查询字段信息 6.可以直接执行sql脚本 7.兼容 IE6,7,8,9 /Firefox /Google Chrome 这些浏览器都测试过 8.批量删除,自定义复选框样式,可以全选/反选 9.角色分级,集团和分公司的关系 10.权限 横向就是业务部分,具体负责哪块业务,纵向是级别 11.动态报表设置,并且可以导出Excel 12.登陆日记,操作日记,异常日记 13.海量批量删除数据库,调用公共存储过程,参数,表明,主键 特点: UI:传统html css,美观 漂亮 大方 实用 js框架:jquery 系统大部分使用AJAX操作。大大提高了用户体验 功能描述: 1.支持N级菜单导航,菜单显示方式支持目前支持2种模式分别: 菜单(无限级),横向(2级) 2.表单验证,文本框高亮起来 3.可以动态分配权限按钮,分配角色权限,目录结构,栏目的链接都可以修改。 4.可以隐藏左侧导航栏,打开左侧导航栏,默认是打开,table表格都自应大小的 5.动态创建数据表,删除用户表,点击数据 表 可以查询字段信息 6.可以直接执行sql脚本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值