`
weakfi
  • 浏览: 96030 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

基于URL实现权限控制

阅读更多

    最近一直在做毕业设计的后台管理模块。很早以前就想写一篇关于权限控制的文章,苦于一直不理解如何用URL实现。以至于当初设计数据库和编写页面实现的时候都没有将权限的URL考虑进去,当时只想直接匹配权限的名称就可以了。直到前几天在JavaEye论坛上看到了一篇题为《一个简易实用的web权限管理模块的应用与实现》的文章才对基于URL的权限控制有了较深的认识。加上之前一直在用另一种方法来实现相同功能,所以这几天一直在总结这两种方法的优劣之处。

       值得提醒的是,本文只关注基于URL和不基于URL两种方法的优劣之处和具体如何实现。数据库设计不会讲的很详细,虽然那也是很重要的,但是关于它的好坏很难有一个统一的标准,这个要看系统具体实现的功能和对效率的要求如何。其实即使是教科书上面提到的规范在实际应用中也是起到参考作用而已,很多时候我们宁愿牺牲规范来换取效率。总之一句话:简单才是美。如果想深入去研究数据库该如何设计的话建议去看看上面提到的文章中的回复,里面大量回复都是针对数据库设计的。好了,先引用上述文章的一些重点内容先:

 

 >>>>以下为引用内容:

本文介绍一个简易实用的web权限管理模块的应用与实现。

    先介绍数据模型和应用界面,后继对实现细节做选择性阐述。

    数据表关系如下:

 

 

 

 

 

 

 

    该图标明了登陆用户、角色、部门(机构)、用户组、角色和模块功能之间的关系。为方便起见,所有表都只保留必要字段。

      在本系统设计中,如下概念有着相对特殊的含义。

      一、用户(user) 系统的使用者。

      二、部门(org):体现了用户的行政关系,

      三、组(group) :是某相同职能的用户的集合,可以和用户一样与角色产生关联。设置组的目的是为了方便用户的角色分配,减少用户与角色的直接对应关系。用户的角色可以是其 组角色和其直接分配的角色之合集。限于作者的时间和精力,组功能在该系统中没有具体的实现。
     
四、角色(role):角色对应着某些功能(function)的集合,被分配一个角色意味着有权执行这些功能。角色表中的字段"functions"记录相关的功能id,id之间用逗号隔开。

      五、功能(function):系统的一个或者多个执行准入。

      那么如何表现功能以最终实现控制用户的每一个细微动作呢?假如不特定于某种架构,可以这么设计该表字段:

Sql代码 :省略。

    假定有三个web访问路径
 
http://127.0.0.1:8080/app/sys/user.jsp?action=index&userid=1203 
  
http://127.0.0.1:8080/app/sys/user.yuetong?action=add
  http://127.0.0.1:8080/app/sys/user.yuetong?action=update&userid=1203
    
这三个访问点被人为的划分为两个功能准入(当然亦可以是一个或者三个),见下图     

 

 

 

 

 

 

 

 

 

 

   由此可知,功能是衡量用户准入的最小刻度。在用户访问某个地址的时候,我们可以通过解析URL对比他拥有的功能权限来实现权限管理。

     借助于某些架构或者设计思路,可以避免用户直接访问JSP页面,甚至全系统的访问地址都使用同一后缀,这种情况下可以省去SUFFIX字段。 本系统就是这种情况(JSP页面置于WEB-INF下,采用struts2架构)。

     六、功能模块树(function tree):功能的目录组织,起分类的作用。在为角色设定功能的时候,用户界面可以利用带选择框的js树。而这颗js树是后台的功能树表以及功能表的联合 表现形式。功能模块树可以方便的与菜单树建立映射关系,限于作者的时间和精力,该系统并未实现菜单树。

 

>>>>引用结束

 

 

       作者对权限控制这一块估计也是比较有经验了,考虑的东西挺全面的。从他的数据库设计中可以看出真正核心的表只有两个:角色和权限。当然实际开发时一般不太可能设计的这么简单,其他表的作用就是用来优化你的数据模型和方便以后扩展用的。你的数据库设计的灵不灵活、健不健壮、安不安全就看其他表如何设计了。本着简单就是美的原则,我设计的数据库有四个表:

 

 

 

 

用户信息:保存用户的基本信息,rolid与角色组的ID关联

角色组:方便用户管理,用户通过角色组和权限发生关联

角色权限:rolidfctid分别和角色组ID,功能列表ID发生关联。have字段的数据类型为Boolean,表示IDrolid的角色组是否具有IDfctid的权限

功能列表:系统的一个或者多个执行准入。由于系统使用了Struts2,所以后缀名统一为action,省略了suffix字段。Module是为了以后功能增多,需要分模块的时候预留的,目前没有实现。

 

       除去那些組的概念,这个设计和上文作者的最大不同就是角色组和权限发生关联的方式,他是用角色组里面的一个字段functions保存权限IDid之间用逗号隔开。我的想法比较简单,既然角色组和权限列表之间是多对多的关系,那就在它们之间新建一个连接表。比较麻烦的就是他们之间的级联关系,如果你没有用HibernateEJB来帮你实现这些级联操作又不想在数据库里面使用外键,那么在用代码操作数据库的时候就要格外留心了,通常我都不能一次就把那些级联关系用代码完整的实现,每次都等到出错了再去找原因。所以动手写代码前还是考虑周全点好。

 

       OK,到具体实现了。第一种方法,假设我不用URL,那么新建权限的时候只需填写权限的名称和描述,很简单。

 


假设我新增了一个叫“管理用户组”的权限,那么我首先需要在用户登录成功后保存他的角色组IDSession里面,然后在对应的Action类的开头添加这些代码:

 

Integer rolid = (Integer) ActionContext.getContext().getSession().get(

              "rolid");   // 获取角色组ID

       if (manager.getRight(rolid, "用户组管理")) {

           // do something

           return "grouplist";

        } else {

           if (manager.getMSG().equals("unallocate")) {

              this.setMsg("对不起,该权限尚未分配!");

           } else if(manager.getMSG().equals("error")) {

              this.setMsg("系统出错!");

           } else {

              this.setMsg("对不起,你无权查看用户组信息!");

           }

           return "error";

}

managerManager类的一个实例, getRight()方法实现查询角色组是否具有某项权限的功能。需要传入角色组ID和权限名称参数。如果查询不到权限名称为“用户组管理”的权限则说明该权限还没有分配。

这样做的缺点很明显:

1.造成代码冗余。假如我的用户组管理又分为显示、新增、修改和删除的功能,那么我需要在每个方法的开头都加上这些代码。那么当权限变多了,就要不断的重复这些代码,重用性低也很不利于以后的维护。

2.   灵活性差。如果我需要对某项权限的名称进行修改,那么只能在后台先把原来的权限删除掉,然后再新建一个和代码里面的名称相同的匹配起来。又或者是直接到代码里面的修改,改完还有重新部署,太麻烦了。

3. 效率低。每次执行判断都需要去数据库执行一次而查询,还是多表连接查询。

4.  暂时想不到

 

造成这些缺点的原因就是在代码里面直接使用到了数据库里面保存的信息。数据库里面的数据是会经常改变的,而代码在项目完成后是不能再改的。不然就叫做升级或者是你系统有漏洞了。所以需要在代码和权限信息之间引入一种相对不变的“变量“,然后让代码和那个“变量“发生关联,而数据库里面只需添加几个字段。那个“变量”就是URL,相信很少人会在web.xmlstruts.xml里面部署完URL后还会去改它。不过即使修改也没关系,容器会自动帮你重新部署,问题不大。

 

第二种方法:使用URL。那么新建权限的时候就要填写多两个信息。



 

同样新增一个叫做“管理用户组”的权限,url/sys/groupparamslist

那么同样在登录成功后需要保存用户的角色组ID,然后实现一个方法去根据角色组ID来查询该角色组拥有的所有权限的URL,然后再用request.getRequestURL()来获得当前URL和用户具有的URL进行匹配。这样做确实变得灵活了,你可以在管理后台尽情修改权限信息,包括名称和URL,只要和你在部署文件中编写的URL保持一致就可以了。但是依然存在代码冗余和效率差的缺点。下面是我的改进方法:

 

       1.  设计一个PowerInfo类用来保存用户的权限信息,当用户登录成功后,新建一个对象把查询数据库返回的信息保存在里面,然后再把对象添加到Session。以后需要进行权限判断的时候都从Session里面取出该对象进行URL匹配。这样就解决了效率低的问题。

public class PowerInfo {
 // 可访问资源
 private ArrayList<String> uri;
 private ArrayList<String> params;
 // 记录用户的越权次数,当次数超过规定的时候自动退出系统
 private int ultravires;
 public ArrayList<String> getUri() {
  return uri;
 }
 public void setUri(ArrayList<String> uri) {
  this.uri = uri;
 }
 public ArrayList<String> getParams() {
  return params;
 }
 public void setParams(ArrayList<String> params) {
  this.params = params;
 }
 public int getUltravires() {
  return ultravires;
 }
 public void setUltravires(int ultravires) {
  this.ultravires = ultravires;
 }

 

      2.  使用Filter过滤所有的用户请求,在Filter里面用当前URL和用户权限的URL进行匹配。这样就解决了代码冗余的问题。实现这个方法的时候有个问题需要注意,当我使用了Struts2后,发现凡是.action后缀的请求都不经过我的Filter。只是.jsp的才会过滤。这个问题具体为什么我也不是很清楚,但和你部署Filter的位置肯定有关,因为当我把自己写的Filter部署到struts2Filter前面的时候问题就解决了。估计如果struts2Filter先在前面处理了.action的请求后不执行chain.doFilter(request,response)就直接返回界面给用户了。

 

以上是本人对基于URL实现权限控制的一些不成熟想法。欢迎各位指出不足之处。

 

分享到:
评论
11 楼 面向对象的猪 2012-08-06  
的确不成熟
10 楼 weakfi 2009-02-19  
jiayunfeng1986 写道

jeffyan 写道当我使用了Struts2后,发现凡是.action后缀的请求都不经过我的Filter。只是.jsp的才会过滤。这个问题具体为什么我也不是很清楚,但和你部署Filter的位置肯定有关,


可能配置错了



struts本身就是用过滤器来工作的 。当然会把。action的后缀全部过滤咯!

可是过滤器处理完后是会把请求再pass到下一个过滤器的喔,这样的话理论上我的Filter应该会接收到请求才对。
9 楼 jiayunfeng1986 2009-02-19  
jeffyan 写道
当我使用了Struts2后,发现凡是.action后缀的请求都不经过我的Filter。只是.jsp的才会过滤。这个问题具体为什么我也不是很清楚,但和你部署Filter的位置肯定有关,


可能配置错了



struts本身就是用过滤器来工作的 。当然会把。action的后缀全部过滤咯!
8 楼 54104 2009-02-19  
acegi思路的简单版。。
7 楼 h521999 2009-02-19  
设计的还不错
6 楼 alvase 2009-02-19  
spring security已经把你做的事情做了,你需要做的只是把它集成到你的项目中去。而没有必要自己写一个访问控制机制。可以研究下spring security,看看他是不是比你的更加成熟?
5 楼 kingkit 2009-02-05  
老大,好文章.
4 楼 guooscar 2009-01-08  
建议一下啊
看看java.security.acl
看看官方的访问控制列表,然后想想 是不是它更简单 更直接 更灵活 更通用。。。
3 楼 weakfi 2009-01-08  
jeffyan 写道

当我使用了Struts2后,发现凡是.action后缀的请求都不经过我的Filter。只是.jsp的才会过滤。这个问题具体为什么我也不是很清楚,但和你部署Filter的位置肯定有关,


可能配置错了


我试过了,好像也不行。能不能说的详细点?
2 楼 jeffyan 2009-01-07  
1.  设计一个PowerInfo类用来保存用户的权限信息,当用户登录成功后,新建一个对象把查询数据库返回的信息保存在里面,然后再把对象添加到Session。以后需要进行权限判断的时候都从Session里面取出该对象进行URL匹配。这样就解决了效率低的问题。


比较赞成, 也可以用过滤器来做 这样做比较完美
1 楼 jeffyan 2009-01-07  
当我使用了Struts2后,发现凡是.action后缀的请求都不经过我的Filter。只是.jsp的才会过滤。这个问题具体为什么我也不是很清楚,但和你部署Filter的位置肯定有关,


可能配置错了

相关推荐

    基于Shiro 拦截URL,实现权限控制

    NULL 博文链接:https://vti-iteye.iteye.com/blog/1963397

    SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建+源代码+文档说明

    基于权限控制访问api或者url资源。 #### 2 . 在你运行该应用之前 : 1. 请修改你自己的数据库配置: /application.yml ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载...

    权限实现实例(Ext+java)

    JOffice中的权限管理是基于...我们知道,在传统的Web项目中,我们都是采用基于URL进行权限控制的。基于EXT的应用也不例外,只不过我们是需要结合前台的功能菜单一起,前台显示出来的功能菜单,其后台均代表可以访问。

    PHP权限管理系统源码

    实现了基本的权限管理,本系统是基于权限节点进行认证,可控制菜单显示隐藏,基于角色控制权限节点。 1、前端框架:layui2.5.6 2、后端框架:ThinkPHP5.1.39LTS 3、后端界面基于layuimini 权限管理系统安装教程: 1...

    基于shiro前后端分离分布式权限管理(完整后端代码)

    前后端分离,前端系统只有html、js 权限管理为shiro,缓存为redis集群 策略:sessionid不随机生成,使用url+用户名作为sessionId

    权限控制的概念及应用

    基于URL粗粒度(常用) 可以基于 Filter 实现 在数据库中存放 用户、权限、访问 URL 对应关系, 当前用户访问一个 URL 地址,查 询数据库判断用户当前具有权限,是否包含这个 URL,如果包含允许访问,如果不包含 ...

    AngularJs基于角色的前端访问控制的实现

    控制页面路由的跳转,没有权限的用户不能跳转到指定url 页面元素的显示控制,没有对应权限的用户不能看到该元素 但在此之前,我们还有一项重要的事要做。 存储用户信息 首先我们要做的,并不是和访问控制有关的事...

    Vue2.0用户权限控制解决方案

    Vue-Access-Control是一套基于Vue/Vue-Router/axios 实现的前端用户权限控制解决方案,通过对路由、视图、请求三个层面的控制,使开发者可以实现任意颗粒度的用户权限控制。 安装 版本要求 Vue 2.0x Vue-router 3.x ...

    详细的微服务开发基础框架

    基于用户-角色-权限控制 权限粒度控制到具体的请求URL 当用户的角色或者权限变动后,已获授权的用户需要重新登录授权 本文围绕上面三个基本需求进行实现。 二、工程说明 设计的框架已经中间件有: Nacos 1.3 ...

    Django web自定义通用权限控制实现方法

    可以通过基于角色对用户权限进行控制: 一、数据模型 1、用户表:用户表和角色表为多对多关系,1个用户可以有多个角色,1个角色可以被多个用户划分; email = models.EmailField( verbose_name='email address',

    基于JAVA SSH+DWZ的权限管理系统 keta-custom

    keta-custom(原keta-security)是一个通用的定制化平台,解决了在web程序再开发过程中遇见的通用功能重复,界面风格迥异;...4.角色管理:角色可以任意分配模块的权限(权限做到了url控制和方法控制)。

    ASP.NET权限应用示例站点

    基于微软的角色权限身份验证机制。进行了简化处理。实现了动态权限树和URL访问的真实控制。代码量极少,不用在每个页面硬编码控制访问。

    Vue-Access-Control 前端用户权限控制解决方案

    Vue-Access-Control是一套基于Vue/Vue-Router/axios 实现的前端用户权限控制解决方案,通过对路由、视图、请求三个层面的控制,使开发者可以实现任意颗粒度的用户权限控制。 整体思路 会话开始之初,先初始化一个...

    基于security_oauth2 构建spring cloud网关的安全认证服务

    基于security_oauth2 构建spring cloud网关的安全认证服务,使用数据库存储和动态请求连接过滤的方式,实现细粒度的url权限控制

    ThinkPHP博客源码XPCMS2.0源码

    XPCMS是由zhu利用业余时间,凭个人兴趣,独立开发的一个...7、后台实现了基于角色的权限控制系统,控制精确到每一个操作,方便多人管理后台。 8、作者将会不断开发插件和模板来丰富该CMS,一切好意见都有被采纳的机会。

    Vue2.0用户权限控制解决方案的示例

    Vue-Access-Control是一套基于Vue/Vue-Router/axios 实现的前端用户权限控制解决方案,通过对路由、视图、请求三个层面的控制,使开发者可以实现任意颗粒度的用户权限控制。 安装 版本要求 Vue 2.0x Vue-router 3....

    基于WebService的分布式多层应用范例

    PersonalManagerWS.WebFacade 安全控制,通过Session识别用户、控制权限、查询时注入数据权限、写业务日志。每个方法被调用时会判断用户是否登录、是否有权限并写业务日志 PersonalManagerWS 以WebService发布服务 ...

    vue用addRoutes实现动态路由的示例

    之前在基于Vue实现后台系统权限控制一文中提到路由权限的实现思路,因为不喜欢在每次路由跳转的before钩子里做判断,所以在初始化Vue实例前对路由做了筛选,再用实际路由初始化Vue实例,代价是登录页需要从Vue实例中...

    基于Spring Boot、Spring Cloud、Vue.js 、Element UI,前后端分离架构的权限管理系统.zip

    接口开发:实现与前端或其他系统交互的接口,定义接口的URL、请求方法和参数,并编写接口的处理逻辑。 业务逻辑开发:根据需求和接口设计,实现具体的业务逻辑。 测试:进行单元测试和集成测试,确保代码的正确性和...

    功能强大的 CMS 源码

    1.后台管理权限分用户和用户组,权限按页面分级,未来还会实现到文章分类的级别控制。 2.管理员在线控制,同一管理员只能同使一个IP在线,多个IP将无法登陆。 3.文件管理实现数据库控制,全站防盗链 4.资讯分类实现...

Global site tag (gtag.js) - Google Analytics