构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(21)-权限管理系统-跑通整个系统
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(21)-权限管理系统-跑通整个系统
这一节我们来跑通整个系统,验证的流程,通过AOP切入方式,在访问方法之前,执行一个验证机制来判断是否有操作权限(如:增删改等)
原理:通过MVC自带筛选器,在筛选器分解路由的Action和controller来验证是否有权限。
首先我们要理解一下筛选器
筛选器的由来及用途
有时,您需要在调用操作方法之前或运行操作方法之后执行逻辑。
为了对此提供支持,ASP.NET MVC 提供了筛选器。 筛选器是自定义类,可提供用于向控制器操作方法添加操作前行为和操作后行为的声明性和编程性手段。
ASP.NET MVC 支持以下类型的操作筛选器:
授权筛选器。 这些筛选器用于实现 IAuthorizationFilter 和做出关于是否执行操作方法(如执行身份验证或验证请求的属性)的安全决策。 AuthorizeAttribute 类和 RequireHttpsAttribute 类是授权筛选器的示例。 授权筛选器在任何其他筛选器之前运行。
操作筛选器。 这些筛选器用于实现 IActionFilter 以及包装操作方法执行。 IActionFilter 接口声明两个方法:OnActionExecuting 和 OnActionExecuted。 OnActionExecuting 在操作方法之前运行。 OnActionExecuted 在操作方法之后运行,可以执行其他处理,如向操作方法提供额外数据、检查返回值或取消执行操作方法。
结果筛选器。 这些筛选器用于实现 IResultFilter 以及包装 ActionResult 对象的执行。 IResultFilter 声明两个方法:OnResultExecuting 和 OnResultExecuted。 OnResultExecuting 在执行 ActionResult 对象之前运行。 OnResultExecuted 在结果之后运行,可以对结果执行其他处理,如修改 HTTP 响应。 OutputCacheAttribute 类是结果筛选器的一个示例。
异常筛选器。 这些筛选器用于实现 IExceptionFilter,并在 ASP.NET MVC 管道执行期间引发了未处理的异常时执行。 异常筛选器可用于执行诸如日志记录或显示错误页之类的任务。 HandleErrorAttribute 类是异常筛选器的一个示例。
创建自定义操作筛选器
框架将先调用操作筛选器的 OnActionExecuting 方法,然后再调用以操作筛选器特性标记的任意操作方法。 同样,该框架将在操作方法完成后调用 OnActionExecuted 方法。
调用 OnResultExecuting 方法后,要立即调用您的操作返回的 ActionResult 实例。 执行结果后,紧接着就要调用 OnResultExecuted 方法。 这些方法对于执行日志记录、缓存输出结果之类的操作非常有用。
以上都是理论问题了,说到底我们就是要OnActionExecuting利用这个方法
当一个Action被执行时调用OnActionExecuting判断是否有权限操作。
由于OnActionExecuting涉及到其他用户和权限的访问我们需要添加SysUser和SysRight的BLL和DAL层了
我们还需要一个存储过程[P_Sys_GetRightOperate]用于取模块的当前用户操作权限,这里为什么用存储过程呢,快点呗,反正这快不用怎么维护了
存储过程如下:
USE db
GO /****** Object: StoredProcedure [dbo].[P_Sys_GetRightOperate] Script Date: 12/01/2013 12:25:48 ******/
SET ANSI_NULLS ON
GO SET QUOTED_IDENTIFIER ON
GO -- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
CREATE PROCEDURE [dbo].[P_Sys_GetRightOperate]
@userId varchar(50),@url varchar(200)
AS
--取模块的当前用户操作权限
select distinct KeyCode,IsValid from SysRightOperate where RightId in(
select a.id from SysRight a, SysModule b where RoleId in(
select SysRoleId from SysRoleSysUser where SysUserId =@userId)
and a.ModuleId = b.Id
and b.Url =@url)
and IsValid=1 GO
创建好了把存储过程更新到EF中去,EF5.0将自动创建一个复杂的类型,大家可以打开来看下
创建一个权限的类permModel,我们将获取到的权限保存到这个类中去,这个类最终是一个一个的session转换而来的。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace App.Models.Sys
{
public class permModel
{
public string KeyCode { get; set; }//操作码
public bool IsValid { get; set; }//是否验证
}
}
SysUser的BLL层和SysRight的DAL层了,如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using App.Models;
using App.Models.Sys; namespace App.IDAL
{
public interface ISysRightRepository
{
List<permModel> GetPermission(string accountid, string controller);
}
}
ISysRightRepository
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using App.IDAL;
using App.Models;
using App.Models.Sys; namespace App.DAL
{
public class SysRightRepository : ISysRightRepository,IDisposable
{ /// <summary>
/// 取角色模块的操作权限,用于权限控制
/// </summary>
/// <param name="accountid">acount Id</param>
/// <param name="controller">url</param>
/// <returns></returns>
public List<permModel> GetPermission(string accountid, string controller)
{ using (DBContainer db = new DBContainer())
{
List<permModel> rights = (from r in db.P_Sys_GetRightOperate(accountid, controller)
select new permModel
{
KeyCode = r.KeyCode,
IsValid = r.IsValid
}).ToList();
return rights;
}
}
public void Dispose()
{ }
}
}
SysRightRepository
GetPermission将通过存储过程访问取得数据
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using App.Models.Sys;
using App.Common;
using App.Models; namespace App.IBLL
{
public interface ISysUserBLL
{
List<permModel> GetPermission(string accountid, string controller); }
}
ISysUserBLL
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using App.BLL.Core;
using App.IBLL;
using Microsoft.Practices.Unity;
using App.IDAL;
using App.Models.Sys;
using App.Common;
using App.Models;
using System.Transactions;
namespace App.BLL
{
public class SysUserBLL : BaseBLL, ISysUserBLL
{
[Dependency]
public ISysRightRepository sysRightRepository { get; set; }
public List<permModel> GetPermission(string accountid, string controller)
{
return sysRightRepository.GetPermission(accountid,controller);
} }
}
SysUserBLL
可以把SysRightRepository变成SysUserRepository层,我这样做是为了区分一下而已,SysRight代表权限,SysUser是用户,根据不同的用户获取他的权限
我们创建一个筛选器在App.Admin下的Core创建SupportFilter.cs
添加如下代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using App.Models.Sys;
using App.BLL;
using App.DAL; namespace App.Admin
{
public class SupportFilterAttribute : ActionFilterAttribute
{
public string ActionName { get; set; }
private string Area;
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext); }
/// <summary>
/// Action加上[SupportFilter]在执行actin之前执行以下代码,通过[SupportFilter(ActionName="Index")]指定参数
/// </summary>
/// <param name="filterContext">页面传过来的上下文</param>
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//读取请求上下文中的Controller,Action,Id
var routes = new RouteCollection();
RouteConfig.RegisterRoutes(routes);
RouteData routeData = routes.GetRouteData(filterContext.HttpContext);
//取出区域的控制器Action,id
string ctlName = filterContext.Controller.ToString();
string[] routeInfo = ctlName.Split('.');
string controller = null;
string action = null;
string id = null; int iAreas = Array.IndexOf(routeInfo, "Areas");
if (iAreas > )
{
//取区域及控制器
Area = routeInfo[iAreas + ];
}
int ctlIndex = Array.IndexOf(routeInfo, "Controllers");
ctlIndex++;
controller = routeInfo[ctlIndex].Replace("Controller", "").ToLower(); string url = HttpContext.Current.Request.Url.ToString().ToLower();
string[] urlArray = url.Split('/');
int urlCtlIndex = Array.IndexOf(urlArray, controller);
urlCtlIndex++;
if (urlArray.Count() > urlCtlIndex)
{
action = urlArray[urlCtlIndex];
}
urlCtlIndex++;
if (urlArray.Count() > urlCtlIndex)
{
id = urlArray[urlCtlIndex];
}
//url
action = string.IsNullOrEmpty(action) ? "Index" : action;
int actionIndex = action.IndexOf("?", );
if (actionIndex > )
{
action = action.Substring(, actionIndex);
}
id = string.IsNullOrEmpty(id) ? "" : id; //URL路径
string filePath = HttpContext.Current.Request.FilePath;
AccountModel account = filterContext.HttpContext.Session["Account"] as AccountModel;
if (ValiddatePermission(account, controller, action, filePath))
{
return;
}
else
{
filterContext.Result = new EmptyResult();
return;
}
}
public bool ValiddatePermission(AccountModel account, string controller, string action, string filePath)
{
bool bResult = false;
string actionName = string.IsNullOrEmpty(ActionName) ? action : ActionName;
if (account != null)
{
List<permModel> perm = null;
//测试当前controller是否已赋权限值,如果没有从
//如果存在区域,Seesion保存(区域+控制器)
if (!string.IsNullOrEmpty(Area))
{
controller = Area + "/" + controller;
}
perm = (List<permModel>)HttpContext.Current.Session[filePath];
if (perm == null)
{
using (SysUserBLL userBLL = new SysUserBLL()
{
sysRightRepository = new SysRightRepository()
})
{
perm = userBLL.GetPermission(account.Id, controller);//获取当前用户的权限列表
HttpContext.Current.Session[filePath] = perm;//获取的劝降放入会话由Controller调用
}
}
//当用户访问index时,只要权限>0就可以访问
if (actionName.ToLower() == "index")
{
if (perm.Count > )
{
return true;
}
}
//查询当前Action 是否有操作权限,大于0表示有,否则没有
int count = perm.Where(a => a.KeyCode.ToLower() == actionName.ToLower()).Count();
if (count > )
{
bResult = true;
}
else
{
bResult = false;
HttpContext.Current.Response.Write("你没有操作权限,请联系管理员!");
} }
return bResult;
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
base.OnResultExecuted(filterContext);
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
base.OnResultExecuting(filterContext);
}
} }
这是一个筛选器。所有逻辑代码都在这里了
打开SysSampleController
修改Create方法变为以下
[SupportFilter]
public ActionResult Create()
{
return View();
}
回到筛选器public string ActionName { get; set; },其中ActionName是自定义Action的名称,比如在Create中直接[SupportFilter]那么ActionName取得就是Create,这将和你的数据库操作码进行对应的,那么我的方法是CreateAttr,那么要使用Create这个操作码,怎么办
那么就是
[SupportFilter(ActionName = "Create")]
public ActionResult CreateAttr()
那么类似的写法
[SupportFilter(ActionName = "Index")]
public JsonResult GetList()
Index无需填写操作码将自动创建操作码,如果你拥有一个操作码那么index将被授权,这个是我们与系统之间的一个约定(你可以去掉这个约定,修改代码即可)
假如你拥有增删改权限却没有访问列表的权限,那不是...
OnActionExecuting负责分解,交给ValiddatePermission去生成权限
如果写在Areas区域的也是兼容的,已经做了处理。
如果你越权操作那么将执行 HttpContext.Current.Response.Write("你没有操作权限,请联系管理员!");
目前位置我们已经跑通了整个系统了,接下来就是自动化的用户角色之间的授权和模块的制作了,能跑通,其他都是很简单了,对吧
这一章比较复杂,需要对AOP编程,MVC的筛选器,和路由进行了解,才能读的比较顺。
如果你没有读懂,那么代码敲一遍,那么你也就差不多知道了
代码进行了大量的注释,还不懂那么留言。
目前为止,我们一个基于按钮级别的权限系统已经全部跑通,现在,可以创建一些没有权限的Action来验证了
我创建:(很明显我们数据库没有这个test的 action的权限),所以你别想越权操作了
[SupportFilter]
public ActionResult Test()
{
return View();
}
最后预览
我们预览一个有权限的
感谢大家,花了你宝贵的时间阅读这一节。
构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(21)-权限管理系统-跑通整个系统的更多相关文章
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(1)-前言与目录(持续更新中...)
转自:http://www.cnblogs.com/ymnets/p/3424309.html 曾几何时我想写一个系列的文章,但是由于工作很忙,一直没有时间更新博客.博客园园龄都1年了,却一直都是空空 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(48)-工作流设计-起草新申请
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(48)-工作流设计-起草新申请 系列目录 创建新表单之后,我们就可以起草申请了,申请按照严格的表单步骤和分 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(47)-工作流设计-补充
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(47)-工作流设计-补充 系列目录 补充一下,有人要表单的代码,这个用代码生成器生成表Flow_Form表 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(46)-工作流设计-设计分支
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(46)-工作流设计-设计分支 系列目录 步骤设置完毕之后,就要设置好流转了,比如财务申请大于50000元( ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(45)-工作流设计-设计步骤
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(45)-工作流设计-设计步骤 系列目录 步骤设计很重要,特别是规则的选择. 我这里分为几个规则 1.按自行 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(44)-工作流设计-设计表单
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(44)-工作流设计-设计表单 系列目录 设计表单是比较复杂的一步,完成一个表单的设计其实很漫长,主要分为四 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(43)-工作流设计-字段分类设计
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(43)-工作流设计-字段分类设计 系列目录 建立好42节的表之后,每个字段英文表示都是有意义的说明.先建立 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(42)-工作流设计01
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(42)-工作流设计01 工作流在实际应用中还是比较广泛,网络中存在很多工作流的图形化插件,可以做到拉拽的工 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(40)-精准在线人数统计实现-【过滤器+Cache】
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(40)-精准在线人数统计实现-[过滤器+Cache] 系列目录 上次的探讨没有任何结果,我浏览了大量的文章 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(41)-组织架构
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(41)-组织架构 本节开始我们要实现工作流,此工作流可以和之前的所有章节脱离关系,也可以紧密合并. 我们当 ...
随机推荐
- clientX/Y,pageX/Y,offsetX/Y,layerX/Y,screenX/Y ,offsetTop,offsetLeft 详解
clientX/Y: clientX/Y获取到的是触发点相对浏览器可视区域左上角距离,不随页面滚动而改变 兼容性:所有浏览器均支持 pageX/Y: pageX/Y获取到的是触发点相对文档区域左上角距 ...
- .Net4.0 ashx页面报错:检测到有潜在危险的Request.Form值(转)
原地址:http://zzhi191.blog.163.com/blog/static/1350849520111116518067/ web开发中难免要多到ajax技术. asp.net中我们处理a ...
- js&&node set_cookie、get_cookie
js: function set_cookie(key, val,now){ var exdate = new Date(now); exdate.setDate(exdate.getDate() + ...
- [我的疑问]String? = "Skiy Chan" 中的问号是什么意思?
var optionalName : String? = "Skiy Chan" String? = "Skiy Chan" 中的问号是什么意思?目前还在看ap ...
- Python自动化运维之1、Python入门
Python简介 python是吉多·范罗苏姆发明的一种面向对象的脚本语言,可能有些人不知道面向对象和脚本具体是什么意思,但是对于一个初学者来说,现在并不需要明白.大家都知道,当下全栈工程师的概念很火 ...
- LightOj_1079 Just another Robbery
题目链接 题意: 抢银行(这个背景最爱了), 有n家银行, 每家银行抢劫被抓的概率是p[i],你认为当你被抓的概率低于P的时候是安全的. 问, 你最多能抢劫到多少money. 思路: 抽象成背包问题, ...
- Spring3+MyBatis3整合log4j无法输出SQL语句问题的解决
今天遇到了跟下面文章一模一样的问题,下面文章的解决方案很好,在这里记录保存一下. Spring3+MyBatis3整合无法输出SQL语句问题的解决
- svn代码统计
http://chenzhou123520.iteye.com/blog/1436653
- jQuery设置按钮被点击状态
js和jquery如何使按钮失效,很简单,只要设置disabled属性为true即为不可用状态即可 1.JS方法一: document.getElementByIdx("btn") ...
- 怎么跳出MySQL的10个大坑
淘宝自从2010开始规模使用MySQL,替换了之前商品.交易.用户等原基于IOE方案的核心数据库,目前已部署数千台规模.同时和Oracle, Percona, Mariadb等上游厂商有良好合作,共向 ...