EasyUI根据MVC4+EasyUI的Web开发框架形成之旅–权限决定

本人在上一篇随笔《基于MVC4+EasyUI的Web开发框架形成之旅–框架总体界面介绍》中几乎介绍了根据MVC的Web开发框架的权限决定总体思路。其中的权杖控制就是分为“用户登录身份验证”、“控制器方法权限决定”、“界面元素权限控制”三种控制措施,可以为Web开发框架本身提供了很好用户访问控制和权力控制,使得用户界面彰显菜单、Web界面的按钮和内容、Action的交给控制,均能在一体化权限作用分配和操纵之下。

EasyUI 1

本篇小说紧要细化那七个方面的介绍,重点介绍“控制器方法权限控制”、“界面元素权限决定”那二种权限决定措施。

 1、用户登录控制

报到界面如下所示。

EasyUI 2

其中登录的前台页面代码如下所示,其中可以在登录界面接收验证码(尽管需求的话)。

        //实现用户登录
        function LoginUserInfo() {
            //获取单击用户登录按钮的事件
            $("#btnLogin").click(function () {
                //首先获取到要传递到控制器的参数,并且狗造成Json。UserName,UserPassword,Code
                var postData = {
                    UserName: $("#UserName").val(),
                    Password: $("#Password").val(),
                    Code: $("#Code").val()
                };

                //发送异步请求实现登录 ajax
                $.ajax({
                    url: '/Login/CheckUser',
                    data: postData,
                    cache: false,
                    async: true,
                    type: 'post',
                    success: function (data) {
                        if (data == "OK") {
                            window.location.href = "/Home/Index";

                        } else {
                            alert(data);
                            window.location.href = "/Login/Index";
                        }
                    }
                });
            });
        }

用户登录的后台控制器方法如下所示:

        /// <summary>
        /// 对用户登录的操作进行验证
        /// </summary>
        /// <param name="username">用户账号</param>
        /// <param name="password">用户密码</param>
        /// <param name="code">验证码</param>
        /// <returns></returns>
        public ActionResult CheckUser(string username, string password, string code)
        {
            string result = "";

            bool codeValidated = true;
            if (this.TempData["ValidateCode"] != null)
            {
                codeValidated = (this.TempData["ValidateCode"].ToString() == code);
            }

            if (string.IsNullOrEmpty(username))
            {
                result = "用户名不能为空";
            }
            else if (!codeValidated)
            {
                result = "验证码输入有误";
            }
            else
            {
                string ip = GetClientIp();
                string macAddr = "";
                string identity = BLLFactory<WHC.Security.BLL.User>.Instance.VerifyUser(username, password, MyConstants.SystemType, ip, macAddr);
                if (!string.IsNullOrEmpty(identity))
                {
                    UserInfo info = BLLFactory<WHC.Security.BLL.User>.Instance.GetUserByName(username);
                    if (info != null)
                    {
                        result = "OK";
                        Session["UserInfo"] = info;
                        Session["Identity"] = info.Name.Trim();

                        #region 取得用户的授权信息,并存储在Session中

                        List<FunctionInfo> functionList = BLLFactory<Function>.Instance.GetFunctionsByUser(info.ID, MyConstants.SystemType);
                        Dictionary<string, string> functionDict = new Dictionary<string, string>();
                        foreach (FunctionInfo functionInfo in functionList)
                        {
                            if (!string.IsNullOrEmpty(functionInfo.ControlID) &&
                                !functionDict.ContainsKey(functionInfo.ControlID))
                            {
                                functionDict.Add(functionInfo.ControlID, functionInfo.ControlID);
                            }
                        }
                        Session["Functions"] = functionDict;

                        #endregion
                    }
                }
                else
                {
                    result = "用户名输入错误或者您已经被禁用";
                }
            }

            return Content(result);
        }

从地方的代码,我们得以见到,在用户登录成功后,后台把用户新闻、用户权限列表消息放到了Session里面,方便进行末端的权杖控制。

然后当前端页面得到成功响应并切换到Home的Index视图前,后台会调用Home的控制器,把一部分用户新闻放到了ViewBag对象里面,并协会用户的连带菜单连串,代码如下所示。

    public class HomeController : BaseController
    {
        public ActionResult Index()
        {
            if (CurrentUser != null)
            {
                ViewBag.FullName = CurrentUser.FullName;
                ViewBag.Name = CurrentUser.Name;

                StringBuilder sb = new StringBuilder();
                List<MenuInfo> menuList = BLLFactory<Menu>.Instance.GetTopMenu(MyConstants.SystemType);
                int i = 0;
                foreach (MenuInfo menuInfo in menuList)
                {
                    sb.Append(GetMenuItemString(menuInfo, i));
                    i++;
                }
                ViewBag.HeaderScript = sb.ToString();//一级菜单代码
            }
            return View();            
        }

EasyUI 3

 

2、控制器方法权限决定

 大家知道,对页面的权柄控制,可以分为前端控制和后台代码的主宰,控制器方法的权能控制属于后台代码的控制。为了便于基类代码的权限决定,我们定义一个权力控制键的类,用来记录通用的充实、修改、删除、查看、列表、导出等传统控制元素,代码如下所示。

    /// <summary>
    /// 定义常用功能的控制ID,方便基类控制器对用户权限的控制
    /// </summary>
    [DataContract]
    [Serializable]
    public class AuthorizeKey
    {
        #region 常规功能控制ID
        /// <summary>
        /// 新增记录的功能控制ID
        /// </summary>
        public string InsertKey { get; set; }

        /// <summary>
        /// 更新记录的功能控制ID
        /// </summary>
        public string UpdateKey { get; set; }

        /// <summary>
        /// 删除记录的功能控制ID
        /// </summary>
        public string DeleteKey { get; set; }

        /// <summary>
        /// 查看列表的功能控制ID
        /// </summary>
        public string ListKey { get; set; }

        /// <summary>
        /// 查看明细的功能控制ID
        /// </summary>
        public string ViewKey { get; set; }

        /// <summary>
        /// 导出记录的功能控制ID
        /// </summary>
        public string ExportKey { get; set; } 
        #endregion

        #region 常规权限判断
        /// <summary>
        /// 判断是否具有插入权限
        /// </summary>
        public bool CanInsert { get; set; }

        /// <summary>
        /// 判断是否具有更新权限
        /// </summary>
        public bool CanUpdate { get; set; }

        /// <summary>
        /// 判断是否具有删除权限
        /// </summary>
        public bool CanDelete { get; set; }

        /// <summary>
        /// 判断是否具有列表权限
        /// </summary>
        public bool CanList { get; set; }

        /// <summary>
        /// 判断是否具有查看权限
        /// </summary>
        public bool CanView { get; set; }

        /// <summary>
        /// 判断是否具有导出权限
        /// </summary>
        public bool CanExport { get; set; }

        #endregion

        /// <summary>
        /// 默认构造函数
        /// </summary>
        public AuthorizeKey() { }

        /// <summary>
        /// 常用构造函数
        /// </summary>
        public AuthorizeKey(string insert, string update, string delete, string view = "") 
        {
            this.InsertKey = insert;
            this.UpdateKey = update;
            this.DeleteKey = delete;
            this.ViewKey = view;
        }
    }

有了那几个实体类,我们就可以在控制器的基类BaseController其间达成部分决定逻辑了。首先大家在控制器每一次执行办法前,都对权力进行一个变换,并把控制键存储到ViewBage里面,方便前端页面的决定,如下代码所示。

        /// <summary>
        /// 重新基类在Action执行之前的事情
        /// </summary>
        /// <param name="filterContext">重写方法的参数</param>
        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);

            //得到用户登录的信息
            CurrentUser = Session["UserInfo"] as UserInfo;            
            if (CurrentUser == null)
            {
                Response.Redirect("/Login/Index");//如果用户为空跳转到登录界面
            }

            //设置授权属性,然后赋值给ViewBag保存
            ConvertAuthorizedInfo();
            ViewBag.AuthorizeKey = AuthorizeKey;
        }

中间ConvertAuthorizedInfo()函数是认证登陆用户是不是享有相应的权能的。

        /// <summary>
        /// 对AuthorizeKey对象里面的操作权限进行赋值,用于页面判断
        /// </summary>
        protected virtual void ConvertAuthorizedInfo()
        {
            //判断用户权限
            AuthorizeKey.CanInsert = HasFunction(AuthorizeKey.InsertKey);
            AuthorizeKey.CanUpdate = HasFunction(AuthorizeKey.UpdateKey);
            AuthorizeKey.CanDelete = HasFunction(AuthorizeKey.DeleteKey);
            AuthorizeKey.CanView = HasFunction(AuthorizeKey.ViewKey);
            AuthorizeKey.CanList = HasFunction(AuthorizeKey.ListKey);
            AuthorizeKey.CanExport = HasFunction(AuthorizeKey.ExportKey);
        }

内部BaseController的控制器基类还定义了判断用户是或不是有几许权力的逻辑,如果没有没有权力,就会抛出自定义极度(MyDenyAccessException),代码如下。

        /// <summary>
        /// 用于检查方法执行前的权限,如果未授权,返回MyDenyAccessException异常
        /// </summary>
        /// <param name="functionId"></param>
        protected virtual void CheckAuthorized(string functionId)
        {
            if(!HasFunction(functionId))
            {
                string errorMessage = "您未被授权使用该功能,请重新登录测试或联系管理员进行处理。";
                throw new MyDenyAccessException(errorMessage);
            }
        }

有了地点的这一个逻辑,大家在业务控制器基类(BusinessController<B,
T>)里面,就足以兑现对一部分基本操作的API的权限决定了。

    /// <summary>
    /// 本控制器基类专门为访问数据业务对象而设的基类
    /// </summary>
    /// <typeparam name="B">业务对象类型</typeparam>
    /// <typeparam name="T">实体类类型</typeparam>
    public class BusinessController<B, T> : BaseController
        where B : class
        where T : WHC.Framework.ControlUtil.BaseEntity, new()
    {

        /// <summary>
        /// 插入指定对象到数据库中
        /// </summary>
        /// <param name="info">指定的对象</param>
        /// <returns>执行操作是否成功。</returns>
        public virtual ActionResult Insert(T info)
        {
            //检查用户是否有权限,否则抛出MyDenyAccessException异常
            base.CheckAuthorized(AuthorizeKey.InsertKey);

            bool result = false;
            if (info != null)
            {
                result = baseBLL.Insert(info);
            }
            return Content(result);
        }

        /// <summary>
        /// 更新对象属性到数据库中
        /// </summary>
        /// <param name="info">指定的对象</param>
        /// <param name="id">主键ID的值</param>
        /// <returns>执行成功返回<c>true</c>,否则为<c>false</c>。</returns>
        public virtual ActionResult Update(string id, FormCollection formValues)
        {
            //检查用户是否有权限,否则抛出MyDenyAccessException异常
            base.CheckAuthorized(AuthorizeKey.UpdateKey);

            T obj = baseBLL.FindByID(id);
            if (obj != null)
            {
                //遍历提交过来的数据(可能是实体类的部分属性更新)
                foreach (string key in formValues.Keys)
                {
                    string value = formValues[key];
                    System.Reflection.PropertyInfo propertyInfo = obj.GetType().GetProperty(key);
                    if (propertyInfo != null)
                    {
                        try
                        {
                            // obj对象有key的属性,把对应的属性值赋值给它(从字符串转换为合适的类型)
                            //如果转换失败,会抛出InvalidCastException异常
                            propertyInfo.SetValue(obj, Convert.ChangeType(value, propertyInfo.PropertyType), null);
                        }
                        catch { }
                    }
                }
            }

            bool result = baseBLL.Update(obj, id);
            return Content(result);
        }

 

3、界面元素权限决定

俺们从上面万分Web开发框架的主界面图可以看出,里面对于某个特定的事务,增添、修改、、查看、删除等操作都放在了EasyUI的DataGrid工具栏里面了,为了动态控制用户能访问的界面按钮,大家需求结合用户权限集合举办界面呈现,首先大家把ToolBar放到一个层里面举办定义,如下代码所示。

        //实现对DataGird控件的绑定操作
        function InitGrid(queryData) {
            $('#grid').datagrid({   //定位到Table标签,Table标签的ID是grid
                url: '/Information/FindWithPager',   //指向后台的Action来获取当前用户的信息的Json格式的数据
                title: '通知公告',
                iconCls: 'icon-view',
                height: 650,
                width: function () { return document.body.clientWidth * 0.9 },//自动宽度
                nowrap: true,
                autoRowHeight: true,
                striped: true,
                collapsible: true,
                pagination: true,
                pageSize: 50,
                pageList: [50, 100, 200],
                rownumbers: true,
                //sortName: 'ID',    //根据某个字段给easyUI排序
                sortOrder: 'asc',
                remoteSort: false,
                idField: 'ID',
                queryParams: queryData,  //异步查询的参数
                columns: [[
                     { field: 'ck', checkbox: true },   //选择
                     { title: '标题', field: 'Title', width: 350, sortable: true },
                     { title: '编辑者', field: 'Editor', width: 80, sortable: true },
                     { title: '编辑时间', field: 'EditTime', width: 150, sortable: true },
                     { title: '附件', field: 'Attachment_GUID', width: 250, sortable: true }
                ]],
                toolbar: "#gridtoolbar",

接下来在HTML里面添加gridtoolbar的层定义,作为easyUI的报表控件的工具条。由于采用了HTML协理类来促成界面控件代码控制转变,因而曾经得以达到了界面权限的支配了。使用那种HTML层定义的工具条定义格局,比通过脚本定义的工具条效果少了一个分隔线,其余的都依然一样的。

EasyUI 4

    <div id="gridtoolbar" style="padding: 5px; height: auto">
        <div style="margin-bottom: 5px">
            @if (@ViewBag.AuthorizeKey.CanInsert)
            {
                @Html.ActionLink("添加", null, null, new {onclick="ShowAddDialog()", data_options="iconCls:'icon-add', plain:true", @class = "easyui-linkbutton", href="javascript:void(0)"})
            }
            @if (@ViewBag.AuthorizeKey.CanUpdate)
            {
                @Html.ActionLink("修改", null, null, new {onclick="ShowEditOrViewDialog()", data_options="iconCls:'icon-edit', plain:true", @class = "easyui-linkbutton", href="javascript:void(0)"})
            }
            @if (@ViewBag.AuthorizeKey.CanDelete)
            {
                @Html.ActionLink("删除", null, null, new {onclick="Delete()", data_options="iconCls:'icon-remove', plain:true", @class = "easyui-linkbutton", href="javascript:void(0)"})
            }
            @if (@Html.HasFunction("Information/View"))
            {
                @Html.ActionLink("查看", null, null, new {onclick="ShowEditOrViewDialog('view')", data_options="iconCls:'icon-table', plain:true", @class = "easyui-linkbutton", href="javascript:void(0)"})
            }
            @Html.ActionLink("刷新", null, null, new {onclick="$('#grid').datagrid('reload');", data_options="iconCls:'icon-reload', plain:true", @class = "easyui-linkbutton", href="javascript:void(0)"}) 

        </div>
    </div>

地点运用了二种方法来判断用户的权能的,一种是接纳这种ViewBag对象的树形进行判定,如下所示。

@if (@ViewBag.AuthorizeKey.CanDelete)

还有一种是使用HTML扶助类的伸张方法开展判断,这种艺术适用于一些非同平日的权位控制集合的判断,如下所示

@if (@Html.HasFunction("Information/View"))

内部HTML协助类方法是透过扩张静态方法举行落实,代码如下所示。

    public static class HtmlHelpers
    {
        public static bool HasFunction(this HtmlHelper helper, string functionId)
        {
            return Permission.HasFunction(functionId);
        }

        public static bool IsAdmin()
        {
            return Permission.IsAdmin();
        }
    }

地点的界面控制格局,是通过决定界面代码的变通与否进行权力控制的,前面大家讲了,通过后台代码的控制器方法也是可以完成控制,而且是抛出自定义的错误,那么大家在运用Ajax方法调用的时候,也足以对那个错误音讯举行自己突显,指示用户权限不足,前端页面操作代码如下。

        //绑定添加按钮的事件
        function BindAddEvent() {
            $("#btnAddOK").click(function () {
                //判断表单的信息是否通过验证
                var validate = $("#ffAdd").form('validate');
                if (validate == false) {
                    return false;
                }

                var postData = $("#ffAdd").serializeArray();
                $.post("/Information/Insert", postData, function (data) {
                    if (data = "true") {
                        //添加成功  1.关闭弹出层,2.刷新DataGird
                        $.messager.alert("提示", "添加成功");
                        $("#DivAdd").dialog("close");
                        $("#grid").datagrid("reload");
                        $("#ffAdd").form("clear");

                        //本页面的类型为【通知公告】,固定不变
                        $("#Category").val("通知公告");
                    }
                    else {
                        $.messager.alert("提示", "添加失败,请您检查");
                    }
                }).error(function () {
                    $.messager.alert("提示", "您未被授权使用该功能,请联系管理员进行处理。", 'warning');
                });
            });
        }

EasyUI 5

 以上就是自个儿对Web开发框架中的权限控制多少个地点的笔触和代码,希望一得之见,得到大家更好的申报和支撑。

 

据悉MVC4+EasyUI的Web开发框架的多如牛毛小说:

根据MVC4+EasyUI的Web开发框架形成之旅–总体介绍

依据MVC4+EasyUI的Web开发框架形成之旅–MVC控制器的设计

据悉MVC4+EasyUI的Web开发框架形成之旅–界面控件的使用

基于MVC4+EasyUI的Web开发框架形成之旅–附件上传组件uploadify的接纳

依照MVC4+EasyUI的Web开发框架形成之旅–框架总体界面介绍

按照MVC4+EasyUI的Web开发框架形成之旅–基类控制器CRUD的操作

据悉MVC4+EasyUI的Web开发框架形成之旅–权限决定

依据MVC4+EasyUI的Web开发框架经验总括(1)-利用jQuery Tags Input
插件显示选取记录

按照MVC4+EasyUI的Web开发框架经验总括(2)-
使用EasyUI的树控件营造Web界面

根据MVC4+EasyUI的Web开发框架经验统计(3)-
使用Json实体类创设菜单数据

基于MVC4+EasyUI的Web开发框架经验计算(4)–使用图表控件Highcharts

依照MVC4+EasyUI的Web开发框架经验计算(5)–使用HTML编辑控件CKEditor和CKFinder

依照MVC4+EasyUI的Web开发框架经验计算(6)–在页面中动用下拉列表的拍卖

根据MVC4+EasyUI的Web开发框架经验总括(7)–已毕省份、城市、行政区三者联动

据悉MVC4+EasyUI的Web开发框架经验计算(8)–完结Office文档的预览

基于MVC4+EasyUI的Web开发框架经验总计(9)–在Datagrid里面完结外键字段的转义操作

根据MVC4+EasyUI的Web开发框架经验总括(10)–在Web界面上贯彻多少的导入和导出

依照MVC4+EasyUI的Web开发框架经验总计(11)–使用Bundles处理简化页面代码

根据MVC4+EasyUI的Web开发框架经验计算(12)–利用Jquery处理多少交互的两种艺术

根据MVC4+EasyUI的Web开发框架经验总计(13)–DataGrid控件完结机关适应宽带中度

据悉MVC4+EasyUI的Web开发框架经验总括(14)–自动生成图标样式文件和图标的挑选操作