zoukankan      html  css  js  c++  java
  • MVC3权限设计详解

    1.设计过滤器:

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
        public class OperationCheckAttribute : ActionFilterAttribute
        {
            /// <summary>
            /// 是否异步触发的验证。
            /// 如果前台用ajax执行Action,IsAsync=true;否则IsAsync=false。
            /// 这样做的目的是当没有权限时给出不同的提示方式.
            /// (直接点Url打开页面时没有权限就跳转到没有权限提示页面,
            /// ajax点击按钮时就以弹出框形式提示)
            /// 
            /// </summary>
            public bool IsAsync { get; set; }
    
    
            /// <summary>
            /// 操作代码1101,1102,1103
            /// </summary>
            public string OpCode { get; set; }
    
            /// <summary>
            /// 模块操作代码
            /// </summary>
            public string OpModel { get; set; }
    
            /// <summary>
            /// 标记Key
            /// </summary>
            public string PmKey { get; set; }
    
            /// <summary>
            /// 标记Key
            /// </summary>
            public string PmValue { get; set; }
    
            /// <summary>
            /// 运算类型= true 或 != false
            /// </summary>
            public bool IsNull { get; set; }
    
            private bool actionCheck = false;
            /// <summary>
            /// Action方法执行前执行
            /// </summary>
            /// <param name="filterContext"></param>
            public override void OnActionExecuting(ActionExecutingContext filterContext)
            {
                if (!string.IsNullOrEmpty(PmKey))
                {
                    //PmKey 不为空 PmValue 为空时,确定一个Action方法有多个权限判断
                    string value =null;
                    if(filterContext.ActionParameters[PmKey]!=null)
                        value = Convert.ToString(filterContext.ActionParameters[PmKey]);
                    if (PmValue == null)
                    {
                        if (string.IsNullOrWhiteSpace(value) && IsNull)
                        {
                            actionCheck = true;
                        }
                        else if (!string.IsNullOrWhiteSpace(value) && !IsNull)
                        {
                            actionCheck = true;
                        }
                    }
                    //PmKey 不为空 PmValue 不为空时,确定一个Action方法有多个权限判断
                    else if (!value.Equals(null))
                    {
                        if (value.ToLower() == PmValue.ToLower())
                            actionCheck = true;
                    }
                }
                else if (!string.IsNullOrEmpty(OpCode))
                {
                    actionCheck = true;
                }
    
                if (actionCheck)
                {
                    bool isViewPage = true;
                    if (filterContext.HttpContext.Request.HttpMethod.ToUpper() == "POST")
                    { isViewPage = false; }
    
                    UserManageBusiness userManage = new UserManageBusiness();
                    TSysUser model = HttpContext.Current.Session["_sso_elab_user_"] as TSysUser;
                    if (model != null)
                    {
                        bool isOk = userManage.AuthCheck(model.UserID, OpCode);//权限验证
                        if (!isOk)
                        {
                            if (isViewPage)
                                filterContext.Result = new RedirectResult("~/Home/PurviewCheck");
                            else
                                filterContext.Result = new ContentResult { Content = "0" };//为前端是用ajax提交,返回是JsonResult的提供无权限处理
                        }
                    }
                    else
                    {
                        filterContext.Result = new RedirectResult("~/Home/PurviewCheck");
                    }
                }
                base.OnActionExecuting(filterContext);
            }
    
            /// <summary>
            /// Action方法执行后返回前执行
            /// 处理界面按钮显示
            /// </summary>
            /// <param name="filterContext"></param>
            public override void OnResultExecuting(ResultExecutingContext filterContext)
            {
                actionCheck = false;
                
                UserManageBusiness userManage = new UserManageBusiness();
                OperationBusiness operationBusiness = new OperationBusiness();
                string sAction = filterContext.RouteData.Values["action"].ToString();
                TSysUser model = HttpContext.Current.Session["_sso_elab_user_"] as TSysUser;
                if (model != null)
                {
                    if (!string.IsNullOrEmpty(OpModel))
                    {
                        TSysRoleUserMapping mapping = userManage.FindRoleUserMap(model.UserID);
                        DataTable dt = operationBusiness.FindListMarkedByRole(mapping.RoleID);
                        DataRow[] dr = null;
                        if (OpModel == "00")
                        {
                            dr = dt.Select("");
                        }
                        else
                        {
                            dr = dt.Select("OpModel=" + OpModel);
                        }
                        foreach (DataRow item in dr)
                        {
                            //审批页面特殊处理:只能让域配置的区域管理员课件
                            if (item["OpCode"].ToString()=="1105")
                            {
                                filterContext.Controller.ViewData.Add("Limited" + item["OpCode"],
                                    userManage.ApproveLimited(model.UserID, model.DomainID) ? "" : "display:none");
                            }
                            else
                            {
                                filterContext.Controller.ViewData.Add("Limited" + item["OpCode"],
                                    bool.Parse(item["RoleMark"].ToString()) ||
                                    userManage.BeyondLimited(model.UserID, mapping.RoleID) ? "" : "display:none");
                            }
                        }
                    }
                }
                else
                {
                    filterContext.Result = new RedirectResult("~/Home/PurviewCheck");
                }
            }
    
        }

    2.后台方法添加过滤器:(含新增和编辑是同一页面这种复杂的处理)

    [OperationCheck(OpCode = "0401", PmKey = "isCreate", PmValue = "true")]
            [OperationCheck(OpCode = "0402", PmKey = "isCreate", PmValue = "false")]
            public ActionResult AddDomain(Guid? domainId, string isCreate)
    {
    //...
    return View(orgDomain);
    }
    [HttpPost]
            [OperationCheck(OpCode = "0401", PmKey = "isCreate", PmValue = "true")]
            [OperationCheck(OpCode = "0402", PmKey = "isCreate", PmValue = "false")]
            public JsonResult Add(TSysDomain domain, string isCreate)
    {
    //...
    return Json(new {Id=...});
    }

    3.前台连接页面事件,过滤器返回的是页面,前端不用处理

    $("#btnShowNew").click(function () {
                    var row = $('#DomainTable').treegrid('getSelections');
                    if (row != null && row.length > 0) {
                        var domainID = "";
                        if (row.length > 1) {
                            alert(Language_Domain_EditOnlyCanSelectOneToCreateWarning);
                        }
                        else {
                            domainID = row[0].DomainID;
                            //var css = row[0].CSSFileName;
                            if (row[0].Enable == false) {
                                alert("该区域已冻结,不能在此域下新增!");
                            }
                            else {
                                var url = '@Url.Action("AddDomain", "Domain")' + "?isCreate=true" + "&domainId=" + domainID;
                                location.href = url;
                            }
                            //window.open(url);//这种方式有问题
                        }
                    }
                    else {
                        var url = '@Url.Action("AddDomain", "Domain")' + "?isCreate=true";
                        location.href = url;
    
                    }
                })

    功能按钮显示隐藏:

    <div class="classdetail_btn_box01" style="@ViewData["Limited0401"]">
                      <div class="classdetail_btn_box0101">
                          @*<a href="@Url.Action("AddDomain", "Domain")"><span id="btnShowNew" style="@ViewData["Limited0401"]" class="classdetail_btn_box0102 domains_btn_box"></span></a>*@
                          <span id="btnShowNew" class="classdetail_btn_box0102 domains_btn_box"></span>
                      </div>
                 </div>

    4.在用Ajax提交事件中,要自行处理经过滤器过滤后的结果,

    $.ajax({
                    url: '@Url.Action("Add", "Domain")' + "?isCreate=" + '@Session["isCreate"]',
                    type: "POST",
                    async: false, //代表同步
                    data: {
                        xDomainId: $("#DomainID").val(),
                        xParentId: $("#ParentID").val(),
                        xParentName: encodeURIComponent($("#ParentDomainName").val()),
                        xDomainName: encodeURIComponent($("#DomainName").val()),
    。。。。。 }, success: function (result) { if (result == "0") { window.location.href = '@Url.Content("~/Home/PurviewCheck")' } else { if (result.DomainID != '@Guid.Empty') { window.location.href = '@Url.Content("~/Domain/AddDomain")' + "?domainId=" + result.DomainID + "
    &isCreate=false"; } } }, error: function (result) { alert(result.message); } });

    因为在Ajax中,执行过滤器后最终会跑到我们的success代码中,
    过滤器执行后的结果就是result,此时result是html页面代码(含js代码),这个js代码不会自己执行的,要自己去处理。

    即使把过滤器中filterContext.Result = new ContentResult { Content = ""<script type='text/javascript'>alert('权限验证不通过!');history.go(-1);</script>"" };它也不会去执行,Ajax这种提交不同于简单的页面URL连接,不管有没用进后台,如果没有权限,只要语法没错,它依然会执行success函数.

    ==>上面这段经同事验证是不正确的,用JS可以实现

    不用走Ajax Success函数后面的代码(如果验证是没有权限的话)

    在公用的JS重加入如下代码:

    /*Ajax没有权限操作,跳转*/
    $(function () {
        $("body").ajaxComplete(function (event, request, settings) {
            if (request.responseText == "NotAuthorized") {
                window.location.href = window.parent.document.URL + "/Home/PurviewCheck";
            }
        });
    })

    ,所用上面的Success函数可以修改如下:

    success: function (result) {
                        if (result.DomainID.length == 32) {
                            if (result.DomainID != '@Guid.Empty') {
                                window.location.href = '@Url.Content("~/Domain/AddDomain")' + "?domainId=" + result.DomainID + "&isCreate=false";
                            } 
                        }
    
                    },
                    error: function (result) {
                        alert(result.responseText);
                    }

    Fitler如下改:

    filterContext.Result = new ContentResult { Content = "NotAuthorized" };

    经验证,这样也是不对的,第一次可以 ,多试几次就多往下执行了。

    于是,想到了ajax的几个事件的执行循序,

    (参考园子里张子秋的博客:http://www.cnblogs.com/zhangziqiu/archive/2009/05/08/jQuery-Learn-6.html

     $("body").ajaxError(function (event, request, settings, errorThrown) (异常时执行)

     $("body").ajaxStart(function (event, request, settings, errorThrown)(AJAX 请求开始时执行函数)

     $("body").ajaxSendfunction (event, request, settings, errorThrown)(AJAX 请求发送前执行函数)

     $("body").ajaxSucess(function (event, request, settings, errorThrown)(AJAX 请求成功时执行函数)

     $("body").ajaxCompleted(function (event, request, settings, errorThrown)(AJAX 请求完成时执行函数)

     $("body").ajaxStop(function (event, request, settings, errorThrown)(AJAX 请求结束时执行函数)

    结合我们的过滤器,执行循序如下:

    ajax提交->

    ajaxStart,

    ajaxSend,

    Fitler

    ajaxSuccess

    ajaxCompleted

    ajaxStop

    -->重新回到ajax 提交的success函数

    如此一来的话,还是会执行success函数以下的代码,过滤器没有起到拦截的作用。

    想到过滤器中设置错误代码,request.status,参考园子里:http://www.cnblogs.com/wintersun/archive/2011/12/18/2291800.html

    JQuery的全局AjaxError配置,可参考官方
    
    $("#errorh3info").ajaxError(function (event, request, settings) {
    
        $(this).append("<li>settings.url:" + settings.url + "</li>");
    
        $(this).append("<li>request.status:" + request.status + "</li>");
    
        $(this).append("<li>request.statusText:" + request.statusText + "</li>");
    
     
    
        //request.responseText
    
        if (request.responseText != "") {
    
            var jsonValue = jQuery.parseJSON(request.responseText);
    
            $(this).append("<li>ErrorMessage:" + jsonValue.ErrorMessage + "</li>");
    
        }
    
    });
    
    给button增加一个Post请求:
    
    $('#inputajax1').click(function () {
    
        $.post('/Home/YouKnow/'
    
       , { id: 1 }
    
       , function (data) {
    
           $('div#right-box.data').html(data);
    
       });
    
    });
    
    这时View上将显示, 我们将看到ErrorMessage是JSON对象的属性:
    settings.url:/Home/YouKnow/
    request.status:500
    request.statusText:error
    ErrorMessage:Value cannot be null. Parameter name: YouKnow method: fc should not be null 

    在过滤器设置500错误代码,进入ajaxError,如果真能进来,我就可以这样:

    $("body").ajaxError(function (event, request, settings, errorThrown) {
            alert("ajaxError");
            if (request.responseText.indexOf("*|") > 0 && request.status == 500) {
                window.location.href = window.parent.document.URL + "/Home/PurviewCheck";
                return;
            }
        });

    这样便实现拦截了,
    可以有时,你设置了错误代码,它也不进入ajaxError,

    郁闷中,求解!

  • 相关阅读:
    Linux之20——sudo命令
    Linux之18——Linux下安装MySQL及远程连接MySQL
    Linux之17——Git安装及使用以及连接GitHub方法详解
    Linux之16——free性能调优命令
    Linux之15——nc命令详解
    Linux之14——curl命令详解
    Linux之13——常用统计命令之wc
    15 Python 迭代器和生成器
    16 Python 递归函数
    17 python 内置函数
  • 原文地址:https://www.cnblogs.com/8090sns/p/Filter.html
Copyright © 2011-2022 走看看