dorado框架权限控制实现方案参考
系统实现分析
我们在dorado里面要如何利用dorado框架的系统特性来实现权限的细粒度控制呢? 我们知道dorado的操作基本上都是以jsp页面为单位进行的,页面上会有各种各样丰富的可视控件供我们进行各种复杂的业务逻辑的操作,而每个页面在dorado系统中其实就是用一个view来控制和管理的,可以说view就是页面的全部,我们每次访问dorado页面时都会访问一个叫做视图实现,类的基类,它的作用是对dorado页面进行一系列的加载和初始化行为,包括dataset的加载,各种页面上使用到的控件的加载,以及他们的初始化工作,可以说我们能够在页面上看到各种丰富的控件的前提是要访问这个实现类,所以对于页面级别的权限控制我们就可以通过自己实现一个试图实现类来完成对权限的控制,思想是在访问这个dorado页面之前我们会先访问视图实现类,在视图实现类的初始化工作开始之前就先进行身份的验证,如果是合法用户那么允许它进行访问,如果不合法,立即终止对当前页面的加载行为并且跳转页面到一个errorPage上,告诉用户他为何不能访问这个页面。
此系统实现类是由系统加载的,它被默认的配置在%doradoproject%/Configures/setting.xml文件中。默认配置为: 基于这个特性我们就可以做到页面级别的权限控制了。什么是页面级别的权限控制呢?对于不同权限的用户,某些页面是不给开放的,在框架中我们不让他看到被保护页面的菜单超链接就可以做到这一点。当我们完成验证工作之后,对于主框架页面的实现类还要做一件事,那就是根据该用户的权限加载该用户能够访问到的菜单,由于dorado的实现方式可以在server端通过编程来对页面要显示的控件进行控制,所以我们做到这一点是很容易的。当完成这一系列的工作之后我们就完成了页面权限级别的控制了。 有时候我们往往还需要实现组件级别的权限控制,页面上某个控件对与某些用户是不可见的,从而达到该用户“只能看,不能该”的目的。那么在dorado中又如何做到这一点 第5页 共66页 dorado框架权限控制实现方案参考 呢?我们知道dorado的各种组件都有一个ignore属性,该属性如果设置为true那么该组件就无法在页面上面显示,从而达到页面解别控制权限的目的。同样的,我们在访问需要进行控制的页面的实现类中进行这样任务的实施,我们可以通过doradoapi得到所有的页面上的dorado控件,如此一来我们便可以遍历这些控件,并且判断这些控件是否因该显示出来,如果不因该显示则将ignore属性设置为true,反之亦然。 实现过程如下: 当我们访问dorado受保护页面时会先访问我们自定义的视图实现类,在加载过程中会执行initControls方法,我们将”是否显示dorado的控件”这项工作放在这里来做,首先通过session拿到用户从而拿到角色id,我们通过角色的id可以找出该用户是否能够访问当前页面 while(viewsIt.hasNext()){ } if(securityFlag){ } throw new AppSecurityException(); VariantSet roleView=(VariantSet)viewsIt.next(); sql = \dbs.setSql(sql); dbs.parameters().setInt(\VariantSet tempviewConfig = dbs.query(); viewConfig=tempviewConfig.getString(\System.out.println(viewConfig); if(configName.equals(viewConfig)){ } securityFlag=false; viewId = roleView.getInt(\break; 此段代码通过角色id号拿到该角色所有能够访问到的视图的信息,然后通过遍历匹配是否有权限,如果没有权限,会在循环里面将标志为(securiyFlag)设置韦true,从而当跳出循环之后可 第6页 共66页 dorado框架权限控制实现方案参考 以抛出异常,禁止加载过程,当有权限访问之后,我们可以取得一个视图的id号,此时我们就可以通过联合主键(这里的作用是联合主键)角色id和视图id来取得某张视图上面某个角色能够访问到的组件了: sql = \rvc.controlid from role_view_control rvc where rvc.roleid = :roleId and rvc.viewid = :viewId\ dbs.setSql(sql); dbs.parameters().setInt(\dbs.parameters().setInt(\List viewControls=dbs.queryForList(); Iterator controlsIt=viewControls.iterator(); while(controlsIt.hasNext()){ } VariantSet vs = (VariantSet)controlsIt.next(); this.getControl(vs.getString(\通过以上语句,我们将该页面上面该角色不能访问到的控件的ingore属性设置为true,从而不会在页面上显示该组件. 到此我们便达到了权限控制的细粒度这个目的。 当然在实施这样的权限管理框架时我们还需要考虑一下如何进行日志操作和异常的控制。 对于以上权限系统我们需要自定义异常,当出现一般的,不太重大的异常时我们只是显示错误信息给客户看到,但对于特别重大的异常,或者是有重要信息的异常我们就需要记录到数据库中去,便于系统管理员或者系统的维护人员对系统进行恢复。要做到第一点并不难,我们可以自定义一个异常,继承自一个RuntimeException,然后在自定义异常中覆盖原来的getMessage()方法,放入自己需要显示的信息,例如对于一个登陆用户非法登陆的处理,我们可以自定义一个异常命名为SecurityException,然后在getMessage()方法中写入信息:您是非法用户,请按照正常程序进行登陆。在程序中,我们如果得知当前用户为非法用户(可能是没登陆,可能是用户名或者密码错误),即可抛出这样一个异常,后续中利用系统的异常捕获机制将异常的错误信息的到然后写入日志或者数据库。在此也有必要提供一种系统异常捕获的机制,通常jsp页面里面有一个errorPage属性(在<@page>中),它表示当系统发生异常 第7页 共66页 dorado框架权限控制实现方案参考 之后就会跳转到errorPage页面上面,但是这样会有局限性,而且工作量会增大,我们必须在每一个jsp页面上加上这样一个标签,如果以后系统有变动还得每一个页面去修改,这样的页面级的捕获方式是不推荐使用的,我们推荐使用系统级别的异常捕获,对于一个java web project都会有一个web.xml文件,我们可以在这里配置一个系统级别的节点为: 规则来做了。这样系统级别的转发规则使得页面程序员,逻辑程序员都脱离了要自己逐步进行手工添加各种异常的繁冗的工作,同时还避免了出错的概率,是值得推荐的处理方式。 对于dorado中的异常处理,由于创建dorado工程时就一定定义,如果请求、exception.d这个地址,就会被dorado的过滤器捕获并且转交到dorado的处理机制中处理,我们在这里还可以实现异常处理的基础类,在这个java类里面我们可以自定义异常的处理,需要显示还是写入数据库全部都由您来决定。 在此工程中我们实现系统日志有三种,分别是控制台输出,输出到文件,和记录到数据库中。控制台输出便于开发人员的调试和测试;文件输出日志时,我们可以定义文件以天为单位输出日志到log文件中,并且以当天的时间为日志文件名称,这样的好处是便于管理,以免过大的日志信息使得单个文件难以观看,同时也便于查阅。而记录到数据库中的信息是比前两种要安全和稳定的多的方式,这里记录的一些关键信息会给系统恢复带来关键性的信息点。 在此,还有另外一种思路的权限实现机制,我们可以仿照著名的框架acegi的做法,使用过滤器来完成对权限的控制,我们将权限验证放到一个过滤器中,并且让此过滤器过滤所有的需要保护的页面,并且可以在过滤器中个各种“阀门”操作,使得某些页面在某些权限下可以通过。如果页面中有细粒度的控件需要控制那么可以加上一个安全控制标签,当我们访问受保护控件之前,会先访问这个权限控制的标签,在标签里面我们做了权限判断,如果权限足够则让该jsp页面显示标签体中的内容,否则不显示。 第8页 共66页

