最近一直在做毕业设计的后台管理模块。很早以前就想写一篇关于权限控制的文章,苦于一直不理解如何用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关联
角色组:方便用户管理,用户通过角色组和权限发生关联
角色权限:rolid和fctid分别和角色组ID,功能列表ID发生关联。have字段的数据类型为Boolean,表示ID为rolid的角色组是否具有ID为fctid的权限
功能列表:系统的一个或者多个执行准入。由于系统使用了Struts2,所以后缀名统一为action,省略了suffix字段。Module是为了以后功能增多,需要分模块的时候预留的,目前没有实现。
除去那些組的概念,这个设计和上文作者的最大不同就是角色组和权限发生关联的方式,他是用角色组里面的一个字段functions保存权限ID,id之间用逗号隔开。我的想法比较简单,既然角色组和权限列表之间是多对多的关系,那就在它们之间新建一个连接表。比较麻烦的就是他们之间的级联关系,如果你没有用Hibernate或EJB来帮你实现这些级联操作又不想在数据库里面使用外键,那么在用代码操作数据库的时候就要格外留心了,通常我都不能一次就把那些级联关系用代码完整的实现,每次都等到出错了再去找原因。所以动手写代码前还是考虑周全点好。
OK,到具体实现了。第一种方法,假设我不用URL,那么新建权限的时候只需填写权限的名称和描述,很简单。
假设我新增了一个叫“管理用户组”的权限,那么我首先需要在用户登录成功后保存他的角色组ID到Session里面,然后在对应的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";
}
manager是Manager类的一个实例, getRight()方法实现查询角色组是否具有某项权限的功能。需要传入角色组ID和权限名称参数。如果查询不到权限名称为“用户组管理”的权限则说明该权限还没有分配。
这样做的缺点很明显:
1.造成代码冗余。假如我的用户组管理又分为显示、新增、修改和删除的功能,那么我需要在每个方法的开头都加上这些代码。那么当权限变多了,就要不断的重复这些代码,重用性低也很不利于以后的维护。
2. 灵活性差。如果我需要对某项权限的名称进行修改,那么只能在后台先把原来的权限删除掉,然后再新建一个和代码里面的名称相同的匹配起来。又或者是直接到代码里面的修改,改完还有重新部署,太麻烦了。
3. 效率低。每次执行判断都需要去数据库执行一次而查询,还是多表连接查询。
4. 暂时想不到
造成这些缺点的原因就是在代码里面直接使用到了数据库里面保存的信息。数据库里面的数据是会经常改变的,而代码在项目完成后是不能再改的。不然就叫做升级或者是你系统有漏洞了。所以需要在代码和权限信息之间引入一种相对不变的“变量“,然后让代码和那个“变量“发生关联,而数据库里面只需添加几个字段。那个“变量”就是URL,相信很少人会在web.xml或struts.xml里面部署完URL后还会去改它。不过即使修改也没关系,容器会自动帮你重新部署,问题不大。
第二种方法:使用URL。那么新建权限的时候就要填写多两个信息。
同样新增一个叫做“管理用户组”的权限,url为/sys/group,params为list。
那么同样在登录成功后需要保存用户的角色组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部署到struts2的Filter前面的时候问题就解决了。估计如果struts2的Filter先在前面处理了.action的请求后不执行chain.doFilter(request,response)就直接返回界面给用户了。
以上是本人对基于URL实现权限控制的一些不成熟想法。欢迎各位指出不足之处。
分享到:
相关推荐
在这个主题中,“基于Shiro拦截URL,实现权限控制”意味着我们将探讨如何利用Shiro来管理应用程序中的访问权限,确保用户只能访问他们被授权的资源。 首先,我们需要理解Shiro的三个核心概念: 1. 身份验证...
本文将详细探讨如何通过`Filter`实现权限控制,以及与RBAC(Role-Based Access Control,基于角色的访问控制)的关系。首先,让我们理解`Filter`的概念。 `Filter`是Java Servlet API中的一个重要组件,它允许我们...
综上所述,SpringBoot结合RBAC思想,可以有效地实现权限控制,覆盖从菜单到页面元素再到URL的多层次管理。通过灵活运用Spring Security提供的各种工具和注解,我们可以构建出安全且易于维护的权限管理系统。
总的来说,这个系统通过SpringBoot构建基础框架,利用Shiro进行权限控制,结合JWT实现无状态认证,借助Jedis提升性能,运用MybatisPlus简化数据库操作,实现了基于URL的权限管理。这种设计不仅提高了系统的安全性,...
本项目是一款基于URL权限控制的Web-admin前端管理系统源码,涵盖525个文件,其中包含147个GIF图片、131个Java源代码文件、61个JavaScript文件、52个HTML文件、41个JPG图片、24个CSS文件、22个PNG图片、15个JSON文件...
在提供的源代码中,你可以看到如何配置Shiro的Filter Chain,如何进行URL权限映射,以及如何在控制器中实现权限检查的示例。通过深入学习和理解这些代码,你可以更好地掌握基于URL的权限管理在实际项目中的应用。
该发明涉及一种基于Vue.js和Django的权限控制系统,它主要关注的是在互联网应用程序中实现高效且严格的用户权限管理。Vue.js是一种轻量级的前端JavaScript框架,它以其易用性、灵活性和组件化特性而受到开发者的青睐...
- 如果默认的过滤器不能满足需求,可以编写自定义过滤器,插入到Spring Security的过滤器链中,实现更复杂的逻辑,比如基于URL、方法或自定义条件的权限控制。 5. **JWT令牌**: - 为了支持API的无状态认证,可以...
在基类中实现权限检查逻辑,这样每个继承类无需重复实现这部分代码。这种方式增加了代码的复用,但可能导致代码结构过于臃肿。 3. 利用AOP框架:例如Spring AOP,可以直接在配置文件或注解中定义切入点,指定哪些...
如果需要更复杂的权限控制,例如基于角色的访问控制(RBAC),可以创建一个`RoleFilter`,检查用户的角色是否允许访问特定的资源。 除了源码实现,还可以借助现有的工具和框架,如Spring Security,它提供了强大的...
总的来说,SpringBoot集成Shiro实现动态URI权限涉及前后端的协同工作,通过Java后端处理权限逻辑,Vue前端展示和交互,结合Shiro的强大功能,可以实现高效、灵活的权限控制系统。在实际项目中,还需要考虑安全性、...
- **基于URL实现权限控制**:讨论了通过URL路径来实现用户权限管理的策略,这在许多Web应用中是非常常见的安全措施。 5. **技术误解** - **不小心被Cglib忽悠了**:揭示了Cglib库在某些特定情况下的不适用性或...
2. **授权**:Shiro支持基于角色的访问控制(RBAC),可以灵活地定义用户角色及权限,如URL拦截、方法级别的权限控制等。 3. **会话管理**:Shiro可以统一管理会话,包括会话超时、分布式会话等,提高系统的安全性。...
### ThinkPHP 基于角色的权限控制 (RBAC) #### 概述 基于角色的访问控制(Role-Based Access Control, RBAC)是一种常见的权限管理机制。本文将深入探讨ThinkPHP框架下的RBAC设计思想及其实现方法,帮助开发者更好...
在基于Spring框架的应用中,构建一个有效的权限控制系统至关重要,因为它确保了只有授权用户才能访问特定的资源或执行特定的操作。Spring框架虽然提供了强大的IoC(Inversion of Control)和AOP(Aspect Oriented ...
首先,Apache Shiro是一个强大且易用的Java安全框架,主要用于身份认证、授权(权限控制)和会话管理。在这个项目中,Shiro作为核心的权限管理组件,负责处理用户的身份验证、角色分配以及对资源的访问控制。Shiro...
在SSM系统中,可以利用Spring Security或Apache Shiro等框架来实现权限控制,包括登录验证、权限校验、URL拦截等功能,确保只有授权用户才能访问特定资源。 5. **毕业设计要素**: 这个系统适合作为毕业设计项目,...
基于权限控制访问api或者url资源。 #### 2 . 在你运行该应用之前 : 1. 请修改你自己的数据库配置: /application.yml ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载...
Filter可以在Servlet执行前后进行预处理和后处理,从而实现数据过滤、登录验证、权限控制等多种功能。 在“javaweb实现的访问权限控制示例”中,我们主要关注的是如何利用Filter进行权限校验。通常,我们会创建一个...