.NET MVC 通过过滤器处理权限问题 配合前端
前段时间公司要求做一个外来人员扫描身份证进入公司 要求内部人员可以预约外来访问 ,就要求做一个权限系统。 这里是配合前端做的一个代码 笔记一下 以防mybase又文件损坏
1.权限过滤器部分
/// <summary> /// 权限验证过滤器 /// </summary> [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] public class AuthAttribute : AuthorizeAttribute { #region 属性 /// <summary> /// 区域名称 /// </summary> private string AreaName { get; set; } /// <summary> /// 当前控制器名称 /// </summary> private string ControllerName { get; set; } /// <summary> /// 当前行为名称 /// </summary> private string ActionName { get; set; } /// <summary> /// 行为类型 /// </summary> private Framework.ActionType ActionType { get; set; } /// <summary> /// 是否允许匿名访问 /// </summary> private bool AllowAnonymous { get; set; } /// <summary> /// 是否登录后即可访问 /// </summary> private bool AllowLogined { get; set; } #region 最终结果 /// <summary> /// 无权使用 /// </summary> private bool Limited { get; set; } /// <summary> /// 未登录 /// </summary> private bool UnLogin { get; set; } /// <summary> /// 登录超时 /// </summary> private bool LoginTimeout { get; set; } #endregion #endregion /// <summary> /// 在过程请求授权时调用 /// 自带的AllowAnonymous特性依旧会执行本方法,但会略过AuthorizeCore方法的执行。 /// </summary> /// <param name="filterContext">筛选器上下文</param> public override void OnAuthorization(AuthorizationContext filterContext) { var AD = filterContext.ActionDescriptor; var CD = AD.ControllerDescriptor; this.AreaName = (filterContext.RouteData.DataTokens["area"] == null ? "" : filterContext.RouteData.DataTokens["area"]).ToString().ToLower(); this.ControllerName = CD.ControllerName; this.ActionName = AD.ActionName; this.AllowAnonymous = false; this.Limited = false; this.LoginTimeout = false; this.UnLogin = false; this.AllowAnonymous = AD.GetCustomAttributes(typeof(AllowAnonymousAttribute), false).Length > 0 || CD.GetCustomAttributes(typeof(AllowAnonymousAttribute), false).Length > 0; this.AllowLogined = false;//AD.GetCustomAttributes(typeof(AllowLoginedAttribute), false).Length > 0 || CD.GetCustomAttributes(typeof(AllowLoginedAttribute), false).Length > 0; var tempActionTypes = AD.GetCustomAttributes(typeof(CatchExceptionAttribute), false); if (tempActionTypes.Length > 0) { var tempActionType = (tempActionTypes[0] as CatchExceptionAttribute); this.ActionType = tempActionType.Type.HasValue ? tempActionType.Type.Value : SF.Framework.ActionType.View; } else { this.ActionType = Framework.ActionType.View; } base.OnAuthorization(filterContext); } /// <summary> /// 授权判定核心 /// </summary> /// <param name="httpContext">筛选器上下文</param> /// <returns></returns> protected override bool AuthorizeCore(HttpContextBase httpContext) { if (this.AllowAnonymous) { return base.AuthorizeCore(httpContext); } else { //bool logined = httpContext.User.Identity.IsAuthenticated; bool logined = Authentication.isLogin(); //string currentUserName = httpContext.User.Identity.Name; string currentUserName = Authentication.getUserName(); if (currentUserName.Equals(SF.Framework.SystemEnvironment.SuperAdminAccountName, StringComparison.CurrentCultureIgnoreCase)) { return true; } if (logined) { if (!this.AllowLogined) { //委托方法进行权限确认 SF.Framework.BLL.Security.Permission permission = new Framework.BLL.Security.Permission(); //委托方法 //permission.OnCheckAuth = CheckPower.Check; //获取权限判定结果 bool auth = permission.CheckAuth(currentUserName, this.AreaName, this.ControllerName, this.ActionName); if (!auth) { this.Limited = true; } } } else { if (string.IsNullOrWhiteSpace(currentUserName)) { this.UnLogin = true; } else { this.LoginTimeout = true; } } } return (this.Limited || this.UnLogin || this.LoginTimeout) ? false : base.AuthorizeCore(httpContext); //不知道为什么这里还要调用一次基类的 } /// <summary> /// 处理未能授权的 HTTP 请求 /// </summary> /// <param name="filterContext">筛选器上下文</param> protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { #region 无权访问 if (this.Limited) { string message = HttpUtility.HtmlEncode(CustomStatusCode.无权访问.ToString() + "指定路径:/" + this.ControllerName + "/" + this.ActionName); if (this.ActionType == Framework.ActionType.View) { filterContext.Result = new RedirectResult("/Blank/ShowMessagePage?message=" + message); } else { filterContext.Result = new HttpStatusCodeResult((int)CustomStatusCode.无权访问, message); filterContext.HttpContext.Response.Write(message); } } #endregion #region 未登录 if (this.UnLogin) { if (this.ActionType == Framework.ActionType.View) { filterContext.Result = new RedirectResult("/Blank/NotLoginPage?message=" + CustomStatusCode.未登录.ToString()); } else { string message = HttpUtility.HtmlEncode(CustomStatusCode.未登录.ToString()); filterContext.Result = new HttpStatusCodeResult((int)CustomStatusCode.未登录, message); filterContext.HttpContext.Response.Write(message); } } #endregion #region 登录超时 if (this.LoginTimeout) { if (this.ActionType == Framework.ActionType.View) { filterContext.Result = new RedirectResult("/Blank/NotLoginPage?message=" + CustomStatusCode.登录超时.ToString()); } else { string message = HttpUtility.HtmlEncode(CustomStatusCode.登录超时.ToString()); filterContext.Result = new HttpStatusCodeResult((int)CustomStatusCode.登录超时, CustomStatusCode.登录超时.ToString()); filterContext.HttpContext.Response.Write(message); } } #endregion } }
2.js部分 通过ajaxsetup来处理auth返回的异常信息
$.ajaxSetup({ statusCode: { 318: function (result) { $.messager.show({ title: 'Error', msg: result.responseText }); }, 319: function (result) { $.messager.show({ title: 'Error', msg: result.responseText }); }, 320: function (result) { $.messager.show({ title: 'Error', msg: result.responseText }); }, } });
3.异常过滤器部分
/// <summary> /// 异常捕获反馈处理 /// </summary> [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class CatchExceptionAttribute : HandleErrorAttribute { /// <summary> /// Action类型 /// </summary> public SF.Framework.ActionType? Type { get; set; } /// <summary> /// 是否记录异常信息 /// </summary> private bool IsRecord { get; set; } public CatchExceptionAttribute() : this(null, true) { } public CatchExceptionAttribute(bool isRecord) : this(null, isRecord) { } public CatchExceptionAttribute(SF.Framework.ActionType actionType) : this(actionType, true) { } /// <summary> /// 构造方法 /// </summary> /// <param name="actionType">Action 类型</param> /// <param name="isRecord">是否记录异常信息</param> public CatchExceptionAttribute(SF.Framework.ActionType? actionType, bool isRecord) { this.Type = actionType; this.IsRecord = IsRecord; } /// <summary> /// 在发生异常时调用 /// </summary> /// <param name="filterContext">操作-筛选器上下文</param> public override void OnException(ExceptionContext filterContext) { string ExceptionID = Guid.NewGuid().ToString(), msg = filterContext.Exception.Message + " [信息编号:" + ExceptionID + "]"; var r = filterContext.RouteData; var context = filterContext.HttpContext; string c = r.Values["controller"].ToString(); string a = r.Values["action"].ToString(); string userName = string.Empty; try { userName = context.User.Identity.Name; } catch { userName = "guest"; } if (string.IsNullOrWhiteSpace(userName)) { userName = "guest"; } string message = "[" + userName + "]发生异常——异常信息:" + msg + ";所在Controller:" + c + ";所在Action:" + a + ";"; if (this.IsRecord) { //可能需要其他记录处理 } SF.Utilities.Log4Helper.Error(this, filterContext.Exception, message); filterContext.ExceptionHandled = true; if (this.Type.HasValue) { if (this.Type.Value == Framework.ActionType.View) { filterContext.Result = new RedirectResult("/Blank/ShowMessagePage?message=" + msg); } else if (this.Type.Value == Framework.ActionType.Data) { filterContext.Result = new SF.Framework.BLL.CommonDataResult(new List<object>()).SerializeToJsonResult(); } else if (this.Type.Value == Framework.ActionType.Operation) { filterContext.Result = new SF.Framework.BLL.OperationResult(false, msg).SerializeToJsonResult(); } } else { base.OnException(filterContext); } } }
处理流程大致是 为每个action添加特殊标记
[AuthAttribute] //权限 [CatchException(Framework.ActionType.Operation)] //异常
Auth 会根据异常过滤器的枚举ActionType来判断action的类型 并根据类型返回result
最后js会根据返回的结果来进行响应
这次的知识点大概在于 OnAuthorization获取被访问的action信息 及获取catchexception过滤器的部分