zoukankan      html  css  js  c++  java
  • mvc的filter

    如果想要记录ajax的请求和输出信息、内部发生异常记录日志、需要登录认证、需要权限判断;那mvc的各种filter可以帮助你实现你想要的。Mvc框架支持5种不同类型的过滤器;我会按照执行顺序进行简单的demo,再简单的代码分享,万一对一个人有益,也是值的。

    1.通过实现IAuthenticationFilter来进行登录认证,如果认证通过继续后续的权限授权等操作;如果认证没有通过跳转登录页面;代码如下:

    public class MvcAuthenticationFilter : FilterAttribute, IAuthenticationFilter
        {
            /// <summary>
            /// 是否需要认证 
            /// </summary>
            public bool IsNeedAuthentication { get; set; }
    
            /// <summary>
            /// 对请求进行身份验证
            /// </summary>
            /// <param name="filterContext"></param>
            public void OnAuthentication(AuthenticationContext filterContext)
            {
                bool flag = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true) || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true);
                if (flag)
                {
                    return;
                }
                if (IsNeedAuthentication)
                {
                    IPrincipal user;
                    if (this.IsAuthenticated(filterContext, out user))
                    {
                        filterContext.Principal = user;
                    }
                    else
                    {
                        this.UnauthenticatedRequest(filterContext);
                    }
                }
            }
    
            protected bool IsAuthenticated(AuthenticationContext filterContext, out IPrincipal user)
            {
                user = filterContext.HttpContext.User;
                var cc = filterContext.Controller.ControllerContext.Controller as BaseController;
                if (cc != null && cc.CurrentAdminInfo != null)
                {
                    IIdentity identity = user.Identity;
                    user = new GenericPrincipal(identity, new[] { "root", "noroot" }); //这里根据实际情况获取用户的角色
                    return true;
                }
                return false;
            }
    
            protected void UnauthenticatedRequest(AuthenticationContext filterContext)
            {
                string returnUrl = filterContext.HttpContext.Request.Url.AbsolutePath;
                string redirectUrl = string.Format("?ReturnUrl={0}", returnUrl);
                string loginUrl = FormsAuthentication.LoginUrl + redirectUrl;
                filterContext.HttpContext.Response.Redirect(loginUrl, true);
            }
            public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext) { }
        }

    2.每个管理后台都少不了权限判断的需求;你可以使用[Authorize(Roles = "r1,r2")] 默认实现进行硬编码,对于用户的权限和角色经常变动的话,或者你需要灵活的处理就需要自定义Authorize,咱们先看下Authorize源代码实现你就会明白


    他的实现原理,先判断是否有匿名访问标签,然后利用AuthorizeCore 授权检查,如果未授权利用HandleUnauthorizedRequest 放回401,跳转到登录页面;很明显授权不通过跳转登录页面不是太合适;另一种实现方式 自定义Authorize 代码如下:

            public new string[] Roles { get; set; }
            protected override bool AuthorizeCore(HttpContextBase httpContext)
            {
                //由原来指定的roles 替换成动态读取的。
                //跟登录用户的roles进行比较。
                if (httpContext == null)
                {
                    throw new ArgumentNullException("httpContext");
                }
                if (!httpContext.User.Identity.IsAuthenticated)
                {
                    return false;
                }
                if (Roles == null)
                {
                    return true;
                }
                if (Roles.Length == 0)
                {
                    return true;
                }
                if (Roles.Any(new Func<string, bool>(httpContext.User.IsInRole)))
                {
                    return true;
                }
                httpContext.Response.StatusCode = 403;
                return false;
            }
    
            protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
            {
                filterContext.Result = new HttpUnauthorizedResult();
            }
    
            public override void OnAuthorization(AuthorizationContext filterContext)
            {
    
                bool flag = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true) || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true);
                if (flag)
                {
                    return;
                }
                string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
                string actionName = filterContext.ActionDescriptor.ActionName;
                string roles = string.Join(",", GetRoles(actionName, controllerName));
                if (!string.IsNullOrWhiteSpace(roles))
                {
                    this.Roles = roles.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                }
    
                base.OnAuthorization(filterContext);
                if (filterContext.HttpContext.Response.StatusCode == 403)
                {
                    //跳转未授权页面
                    filterContext.Result = new RedirectResult("/Other/Noright");
                }
            }

    3.动作过滤器记录一些ajax的输入输出数据,方便排查问题;代码有注释也比较简单直接贴代码了

      public override void OnActionExecuting(ActionExecutingContext filterContext)
            {
                if (filterContext.HttpContext.Request.IsAjaxRequest())
                {
                    var httpContext = filterContext.HttpContext;
                    //输入参数
                    var req = new JavaScriptSerializer().Serialize(HttpContext.Current.Request.Form.AllKeys.ToDictionary(k => k, k => HttpContext.Current.Request.Form[k]));
                    var code = httpContext.Request.GetHashCode();
                    var controllerName = filterContext.RouteData.Values["controller"] as string;
                    var actionName = filterContext.RouteData.Values["action"] as string;
                    var postUrl = controllerName + "/" + actionName;
                    LogHelper.WriteDebug(
                        string.Format("RequestUrl:{0};HashCode:{1}</br>RequestParam{2}",
                       postUrl, code,
                        req));
                }
            }
    
       
            public override void OnActionExecuted(ActionExecutedContext filterContext)
            {
                if (filterContext.HttpContext.Request.IsAjaxRequest())
                {
                    //输出参数
                    var jsonR = filterContext.Result as JsonResult;
                    var res = new JavaScriptSerializer().Serialize(jsonR);
                    LogHelper.WriteDebug(string.Format("OnActionExecuted---返回值:{0}", res));
                }
    
            }

    4.最后是发生异常的处理,mvc默认实现HandleErrorAttribute,但是也不够灵活,查看源代码


     我们定义之后的代码

        public override void OnException(ExceptionContext filterContext)
            {
                string errCode = "";
                string errMsg = "";
                //自定义错误
                if (filterContext.Exception is ClException)
                {
                }
                else
                {
                    errMsg = "未知错误";
                    LogHelper.WriteError(filterContext.Exception.Message);
                }
                //如果是ajax请求
                if (filterContext.HttpContext.Request.IsAjaxRequest())
                {
                    var result = new ExceptionResponse
                    {
                        ErrMsg = errMsg,
                    };
                    filterContext.Result = new JsonResult()
                    {
                        Data = result
                    };
                }//500服务器内部错误
                else
                {
                    filterContext.Result = new ViewResult() { ViewName = "/Views/Other/Seerro.cshtml" };
                }
    
                filterContext.ExceptionHandled = true;//阻止golbal里的错误执行
                filterContext.HttpContext.Response.Clear();
                filterContext.HttpContext.Response.StatusCode = 500;
                filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;//禁用 IIS 自定义错误
            }

     看下弹出的错误效果

  • 相关阅读:
    通过USB转TTL串口下载stm32程序
    实验一:基于STM32F1的流水灯实验(库函数)
    opencv 常用头文件介绍
    OpenCV 1.0在VC6下安装与配置(附测试程序)
    在Angularjs使用中遇到的那些坑
    js和ts关于遍历的几个小总结
    angularjs的启动方式
    关于跨域和如何解决跨域问题的小结
    TypeScript(入门)
    截取字符串部分汇总
  • 原文地址:https://www.cnblogs.com/chengtian/p/7645022.html
Copyright © 2011-2022 走看看