博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
老话题,权限设计及实现!
阅读量:4874 次
发布时间:2019-06-11

本文共 3989 字,大约阅读时间需要 13 分钟。

前言

  以前也写过两篇关于权限这个话题的文章和,最近在新的项目中,权限设计这块做了重新的考虑和设计。一直有人说权限这个东西不能太死,所以我们本着把权限尽量做到透明化,而设计了这样的权限管理。

设计思路

1、因为项目使用的是asp.net mvc,在mvc中一个action就对应的是一个URL,一般来说一个action只会做一件事情,所以我们获取请求的action就可以知道你将要干什么,那么我们把系统中所有的模块全部存放到数据库中,并且把功能按钮也放到数据库中,可以构造成一个树形菜单的形式。如图:

其中,这里分为导航权限和功能权限,导航权限指:系统运行时会自动根据权限分配加载到导航树上去的;功能权限指:这个页面上有哪些按钮。这里我采用一个标识来区分哪些为导航权限,哪些为功能权限。因为登录系统,加载导航栏时只需要获取导航权限进行验证就OK了。

2、保存用户权限,在角色赋权的页面,直接加载整个导航表中的数据,采用树形展示,在角色表中保存模块表的主键ID即可。

3、为角色关联用户则可以直接关联用户的ID或者工号什么的都可以。

4、拉取权限加载导航,用户登录即可去角色表中获取到该用户拥有哪些角色。获取模块表ID,根据模块表ID,获取模块表数据,剔除功能权限,然后动态加载导航。

5、功能权限的验证方案,这也是考虑很久的一个地方,以前的思路就是直接传一个参数值去判断是否显示这个按钮。这次采用了对HTML进行剔除的方式进行功能按钮的隐藏和显示。

具体实现

1、导航权限验证:采用拦截器,在action执行前进行权限验证。

public override void OnActionExecuting(ActionExecutingContext filterContext){    //当前访问地址    string Code = string.Format("/{0}/{1}", filterContext.RouteData.Values["controller"].ToString(), filterContext.RouteData.Values["action"].ToString()).ToLower();    string[] ListResource = ResourceBiz.Instance.Get(new string[] { "Url" }).Select(p => p.Url).Where(p => !string.IsNullOrEmpty(p)).Select(p => p.ToLower()).ToArray();//获取模块表导航代码这个字段与当前URL比对    if (!ListResource.Contains(Code))//模块表中不存在的URL,默认不进行验证        return;    if (!Authentication.GetResourceCode().Contains(Code))//Authentication.GetResourceCode()为当前用户所拥有的权限    {        //验证不通过        ContentResult Content = new ContentResult();        Content.Content = "";        filterContext.Result = Content;    } }

2、验证页面的功能权限:也是采用拦截器,在action执行后,获取即将渲染的HTML源码进行分析及剔除操作。

//获取即将呈现的HTML,剔除功能按钮public override void OnResultExecuted(ResultExecutedContext filterContext){
//用户控件则不进行筛选 if (!filterContext.IsChildAction) filterContext.HttpContext.Response.Filter = new WhitespaceFilter(filterContext.HttpContext.Response, filterContext);//重写}
//重写public class WhitespaceFilter : System.IO.MemoryStream{    private System.IO.Stream Filter = null;    private ResultExecutedContext filterContext = null;    private string Source = string.Empty;    //构造函数,用来接收变量    public WhitespaceFilter(HttpResponseBase HttpResponseBase, ResultExecutedContext filterContexts)    {        Filter = HttpResponseBase.Filter;        filterContext = filterContexts;    }    //读取HTML源码    public override void Write(byte[] buffer, int offset, int count)    {        Source += System.Text.Encoding.UTF8.GetString(buffer);//HTML源码      }    //分析进行权限处理    public override void Close()    {        //当前访问地址        string Code = string.Format("/{0}/{1}", filterContext.RouteData.Values["controller"].ToString(), filterContext.RouteData.Values["action"].ToString()).ToLower();        string[] ListResource = ResourceBiz.Instance.Get(new string[] { "Url" }).Select(p => p.Url).Where(p => !string.IsNullOrEmpty(p)).Select(p => p.ToLower()).ToArray();//获取模块表所有记录        if (ListResource.Contains(Code))//模块表中不存在的URL,默认不进行验证        { //解析处理            HtmlDocument Document = new HtmlDocument();            Document.LoadHtml(Source);            HtmlNode htmlNode = Document.DocumentNode;        /*这里需要获取这个模块下所有的共功能权限,然后跟你所拥有的这个页面的功能权限比对,如果不拥有这个功能权限,则可以根据规则获取到这段HTML,然后删除掉*/            /*_______________________开始分析处理功能按钮,这里可以自己增加验证规则___________________________*/            HtmlNodeCollection hnc = htmlNode.SelectNodes("//a");//获取需要验证的功能按钮HTML,由开发人员自己定义,你也可以给个特定的标识来标识这个标签为功能按钮,譬如:htmlNode.SelectNodes("//a[@class='add']");获取神马的            if (hnc != null)            {                foreach (HtmlNode node in hnc)                {                    //拿到所有A标签,然后把href取出来,跟当前用户所拥有的功能权限比对,如果相等或者包含则删除                    string CodeStr = node.Attributes["href"] != null ? node.Attributes["href"].Value.ToLower() : "";                     node.ParentNode.RemoveAll();                 }            }         }        Filter.Write(System.Text.Encoding.UTF8.GetBytes(Source), 0, System.Text.Encoding.UTF8.GetByteCount(Source));        base.Close();    }}

这样设计的话,系统中关于权限的地方就全部透明化了。只是在功能权限验证时,要把所有情况全部考虑进去,不知道从文字中大家能不能明白我所需要表达的意思,文笔实在太差了。

转载于:https://www.cnblogs.com/jiangbiao/archive/2012/12/03/2799803.html

你可能感兴趣的文章
从抖音关闭评论,看服务治理的重要性
查看>>
MIUI10系统怎么样刷成开发版获得ROOT权限
查看>>
前端内容思维导图
查看>>
Linux下装VirtualBox
查看>>
ORA-12514: TNS:listener does not currently know of service requested in connect descriptor
查看>>
linux下面安装配置LAMP环境
查看>>
libco之协程分析
查看>>
java人机猜拳游戏002user
查看>>
iOS UIButton的使用详解
查看>>
Spring Boot 2(一):Spring Boot 2.0新特性
查看>>
排序问题
查看>>
Java 序列化Serializable详解(附详细例子)
查看>>
FMDB的使用
查看>>
CodeForces--TechnoCup--2016.10.15--ProblemA--Transformation: from A to B
查看>>
android Makefile 的流程—how android makefile work---makefile progress in android
查看>>
Picasso解决 TextView加载html图片异步显示
查看>>
SQL Server如何进行时间比较的代码
查看>>
SSL证书
查看>>
NSQ
查看>>
Trie树【字典树】浅谈
查看>>