基于资源名的MVC权限控制
在程序复杂程度不断上升的过程中,无可避免需要触碰到权限控制,而权限控制又与业务逻辑紧紧相关,市场上出现了大量的权限控制产品,而程序的开发,讲究去繁化简的抽象,在我的开发过程中,逐渐发现程序的权限控制核心不外乎两个方面:1、资源定位;2、访问控制列表。本文主要针对资源定位进行分析,并解决一些我所遇见过的问题。而在MVC上,MVC提供给我们了非常好的访问控制扩展机制,我们能够通过这些机制更好地控制系统权限。
在我们之前的开发中,针对ASP.NET下WebForm进行开发,很多人都采用了继承Page基类自定义BasePage,构造自己的验证逻辑后再将最终的展示页面继承于BasePage,所有的验证逻辑中,也必须解决我上文中提到的两个问题:资源定位和访问控制列表。而WebForm下使用路由机制的机会并不多,意义也并不大,在这个背景下,大多数人产生了这样的错觉:使用URL进行资源定位就够了。我所见过的几个项目,大多采用了这个办法,或者这个办法的细微变种。而WebForm的机制也决定了这个方法是具有一定可行性的,每一个资源(页面)都是一个类,资源定位较为容易。而进入MVC时代后,一切都发生了改变。在MVC的场景下,你将遇到以下几个问题:
1、 路由机制的引入会出现一个资源多个URL的可能以及增加Area等参数后URL的不确定性。
2、 Action重载的问题难以解决。例如一个页面Order,在Get方法下不带参访问是被允许的,而在Post下带参访问是被禁止的,但这两个资源的URL都是 /Order/,在一些第三方库的辅助下,甚至能有更多的重载Action,这就导致URL定位机制的全面失效。
而面对上述情况,用一种什么样的方式进行资源的定位、控制就成为放在我们面前的难题。在MVC下,可以认为每一个方法(Action)即为一个资源(页面),用何种方法能在程序外部控制这些资源使得权限控制能对其轻松进行,这是整个问题的核心。上文说到,每个方法即为一个资源,那我们是否可以将方法名、方法签名作为资源的定位标识?答案是可以的。
在MVC下,进行权限控制,很自然地想到了使用自定义AuthorizationFilter来进行控制,那么在这个Attribute中是可以获得方法相关信息的。
var t = (ReflectedActionDescriptor) filterContext.ActionDescriptor;
var method= t.MethodInfo.ToString();
在派生自FilterAttribute, IAuthorizationFilter的自定义Attribute中,可以根据上面两个方法获取方法的完整签名,包括返回类型、方法名、参数类型。
通过这个方法是可以进行权限控制的,但是这个方法存在着一个致命的缺点:返回值的类型名、参数的类型名,有的是完全限定名,即需要带命名空间,而有的是不完全限定名。而这个完全限定名的获取是较为繁琐的,因此,这个方法的可操作性大大降低。
那如何优雅地定位到我们所需要控制的资源呢?我们是否可以为我们所需要的资源取一个名字,然后在访问控制列表中将这个名字添加进去,每次执行这个Action的时候获取当前Action的名字,然后在访问控制列表中进行比对就可以解决这个问题。那如何将资源进行命名就成了解决问题的关键。代码级的资源控制必须想到元数据,而需要在元数据中增加信息,这个任务自然又落到Attribute的身上。
我们自定义一个Attribute为Action标注资源名称:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public sealed class ResourceCustomerNameAttribute : Attribute
{
private readonly string _resourceName; public ResourceCustomerNameAttribute(string resourceName)
{
_resourceName = resourceName;
} public string ResourceName
{
get { return _resourceName; }
}
}
这个Attribute实现的功能很简单:为资源进行命名(如果方便,使用ID会更高效一点)。
完成了对资源的命名,接下来需要对资源与访问控制列表进行比对,我是这样使用的:继承FilterAttribute, IAuthorizationFilter,在派生类中先获取ResourceCustomerNameAttribute实例
然后用attribute.ResourceName属性与我们的访问控制列表进行比对:
public void OnAuthorization(AuthorizationContext filterContext)
{
var acl = filterContext.HttpContext.Session[SessionName.PermissionSessionName] as IEnumerable<IAcl>; var attNames = filterContext.ActionDescriptor.GetCustomAttributes(typeof(ResourceCustomerNameAttribute), true) as IEnumerable<ResourceCustomerNameAttribute>; var anonymous =filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), true) as IEnumerable<AllowAnonymousAttribute>; if (anonymous != null && anonymous.Any())
{
return;
}
if (acl == null || !acl.Any())
{
filterContext.Result = new RedirectToRouteResult(new System.Web.Routing.RouteValueDictionary(new { Controller = _controller, action = _action }));
}
else
{
var joinResult = (from aclEntity in acl
join attName in attNames on aclEntity.ResourceName equals attName.ResourceName
select attName
).Any(); if (joinResult)
{
return;
}
else
{
filterContext.Result = new RedirectToRouteResult(new System.Web.Routing.RouteValueDictionary(new { Controller = _controller, action = _action }));
}
}
}
如果比对成功则获取相应访问许可,可以对资源进行访问,若比对失败则跳转至授权失败页面。
而在实际的使用过程中,我们在登录成功后,将构造用户的ACL,并将ACL存入Session中,之后用户在每一次的访问中均使用Session中的ACL进行比对,授权。
在这个具体实现中,我有一个难以处理的问题:即用户访问页面时若未授权,则跳转到未授权提示页面,若用户进行基于Json传递的ajax调用时如何向用户提供合适的信息?之前考虑过使用ContentType来判断,可是后来觉得这会导致开发之中的约定过多(更何况我对很多人对Http协议的了解程度并不抱有信心)。不知各位是否有更好的办法来实现多种错误返回信息?望不吝赐教。
模块的具体代码已托管于GitHub:https://github.com/uliian/ULiiAnPermissionControlModule
功能核心模块已经上传,示例正被GFW狂虐~各位稍安勿躁,如有靠谱的全局科学上网方法的同学也希望悄悄告诉我一下~T.T
欢迎参考,提出您的宝贵意见。
基于资源名的MVC权限控制的更多相关文章
- 基于Vue实现后台系统权限控制
原文地址:http://refined-x.com/2017/08/29/基于Vue实现后台系统权限控制/,转载请注明出处. 用Vue/React这类双向绑定框架做后台系统再适合不过,后台系统相比普通 ...
- 利用基于@AspectJ的AOP实现权限控制
一. AOP与@AspectJ AOP 是 Aspect Oriented Programming 的缩写,意思是面向方面的编程.我们在系统开发中可以提取出很多共性的东西作为一个 Aspect,可以理 ...
- 基于RESTful API 设计用户权限控制
RESTful简述 本文是基于RESTful描述的,需要你对这个有初步的了解. RESTful是什么? Representational State Transfer,简称REST,是Roy Fiel ...
- asp.net core mvc权限控制:分配权限
前面的文章介绍了如何进行权限控制,即访问控制器或者方法的时候,要求当前用户必须具备特定的权限,但是如何在程序中进行权限的分配呢?下面就介绍下如何利用Microsoft.AspNetCore.Ident ...
- ASP.NET MVC权限控制思路
在系统开发的时候一个老生常谈的权限管理问题,翻阅了很多的网络资料,但是总感觉离实际使用还有一段距离,其实权限控制无非就几个“请求.页面按钮.字段显示”, 对于前端权限就需要配合JS了, 这里主要展示我 ...
- Laravel 5 中间件、路由群组、子域名路由、 权限控制的基本使用方法
创建控制器: php artisan make:controller Admin/IndexController 创建Middleware: php artisan make:middleware T ...
- .NET MVC权限控制
一.模块 权限控制的主体单位,与MVC里的Cotroller相对应. 二.模块权限 权限控制的最小单位,通过给每一个模块设置权限,可以控制到非常细小的功能. 三.角色 权限拥有者,通过给不同的角色分配 ...
- asp.net core mvc权限控制:权限控制介绍
在进行业务软件开发的时候,都会涉及到权限控制的问题,asp.net core mvc提供了相关特性. 在具体介绍使用方法前,我们需要先了解几个概念: 1,claim:英文翻译过来是声明的意思,一个cl ...
- asp.net core mvc权限控制:在视图中控制操作权限
在asp.net core mvc中提供了权限验证框架,前面的文章中已经介绍了如何进行权限控制配置,权限配置好后,权限验证逻辑自动就会执行,但是在某些情况下,我们可能需要在代码里或者视图中通过手工方式 ...
随机推荐
- 【Git安装】centos安装git
1 yum install git 安装后的默认存放地点/usr/bin/git
- Windows 上安装 pip
1 从 https://pypi.python.org/pypi/pip#downloads 下载安装包 pip-9.0.1.tar.gz 2 解压 pip-9.0.1.tar.gz 3 用CMD ...
- c#进阶之Delegate
委托是什么?答:委托是一种类型 等同与 一个class类,继承System.MulticastDelegate,但mult....gate是一个特殊类,不能够派生 委托的调用,如何去使用 1/委托 ...
- 2017年P4中国峰会北京站 会议小结
2017 P4 中国峰会 北京 本次会议依然侧重介绍P4,并highlight P4的benifit,大致分为以下几类: 1.学术界 - 未来网络的发展,为何提出P4技术? 未来网络和实体经济.其他学 ...
- 【转载】TCP慢启动、拥塞避免、快速重传、快速回复
转载自:TCP慢启动.拥塞避免.快速重传.快速回复 转自:http://blog.csdn.net/itmacar/article/details/12278769 感谢博主的辛勤成果! 为了防止网络 ...
- python 获取文件的修改时间
os.path.getmtime(name) #获取文件的修改时间 os.stat(path).st_mtime#获取文件的修改时间 os.stat(path).st_ctime #获取文件修改时间 ...
- Win10重命名文件夹导致资源管理器卡顿的解决办法
我本机使用的是 Win10 1607,不清楚是因为什么原因导致重命名文件夹时资源管理器会被卡死,找了很长时间终于找到了解决办法,现在我把步骤粘出来以便后续遇到相同问题的朋友能及时解决. 其实操作很简单 ...
- YOLO V3论文理解
YOLO3主要的改进有:调整了网络结构:利用多尺度特征进行对象检测:对象分类用Logistic取代了softmax. 1.Darknet-53 network在论文中虽然有给网络的图,但我还是简单说一 ...
- Java基础七-正则表达式
Java基础七-正则表达式 一.定义: 特定的符号的组合 二.作用: 用于操作字符串数据 三.优缺点 简化代码,但是阅读性差 四.引入 4.1 问题 判断一个号码是否是QQ号? 不是零开头 6-15位 ...
- java反射究竟消耗多少效率
原文出处 一直以来都对Java反射究竟消耗了多少效率很感兴趣,今晚总算有空进行了一下测试 测试被调用的类和方法 package com.spring.scran; public class TestM ...