1、 What? 什么是权限管理?
具体可参见百度:http://baike.baidu.com/view/2108713.htm
名词备注:
数据级权限:百科内的权限管理一文解释的比较不错,但其中的“数据级权限”有的人看来会觉得有点摸不着头脑。数据级权限,即表示权限与特定数据有联系的权限,比方说,某用户只能创建100个用户。这个100,就是数据级权限的一个指标。
2、 How?怎么样实现权限管理?
2.1、一种烦恼
也许很多程序员会在权限管理中遇到这样的一个问题。
大部分项目都需要权限管理系统,但不同的项目背景中,角色的种类和对应的权限灵活多变。往往需要在维护和调研时花费大量的功夫去分析,而最后由于不同客户方不同层面的领导的意见不一或者不同的决策等问题,造成多次的翻工(也许开始你定好了适合他们的权限机制,但后来又有些不可抗拒因素导致你又要修改项目)。
这样的问题是一种无用功,而且是十分让人烦恼的。
如何去解决怎样的问题?
2.2、权限管理架构图
2.2.1、用户user
保存基本的用户名,密码,角色表id和用户状态。
管理员可以修改用户的角色。
PS:系统最基本的状态至少需要保留一个默认管理员账号。
2.2.2、权限privilege
用来判定(vote)功能及数据级权限管理的依据。
项目创建者内置的权限集合,不给与管理的权限。否则将可能造成项目功能的缺陷。
2.2.3、角色role
决定用户具体包含权限列表。
role_privilege连接role与privilege两个表用来表示关系表连接构造many-to-many关系。
同样的,系统默认状态也必须保留至少一种角色为系统自带的管理,这个角色具备系统中全部的权限。也就是说,该角色不受role_ privilege表所限制,会直接读取privilege中的所有权限集。
2.2.4、权限分类privilege_category
为了更加完善的展现权限分配模块,可以构造一个权限分类。
2.3、用SpringSecurity3实现具体功能
具体SpringSecurity3的配置这里就不详细说明了,可参考网上其他资料。因为本文主要讲述的是如何实现RBAC权限管理模块。
注:自定义的权限的命名必须以ROLE_ 开头,例如ROLE_USER_CREATE等。
2.3.1、权限与角色误区
使用SpringSecurity3的时候,网上很多的资料都能让你的模块跑起来。但随之而来的是一些误区。
比方说,会把权限和角色两者混淆。比较经典的例子如下:
Collection<GrantedAuthority> auths=new ArrayList<GrantedAuthority>();
GrantedAuthorityImpl roleAdmin=new GrantedAuthorityImpl("ROLE_ADMIN");
GrantedAuthorityImpl roleUser=new GrantedAuthorityImpl("ROLE_USER");
auths.add(roleAdmin);
auths.add(roleUser);
然后访问权限的配置如下:
<intercept-url pattern="/**" access="ROLE_USER" />
虽然也许看上去没什么问题,但其实存在一定的隐患。因为能访问页面的不是因为他是user,而是因为他有“访问”的权限。
如果后来增加了一个guest的角色,而他能访问系统,但不能含有user的权限。因为user的权限可能有附带很多界面上的功能,但不附上ROLE_USER的话guest又不能访问系统,所以你就不得不修改配置文件中的access。
造成这个的问题的最终原因就是角色和权限混淆了。
2.3.2、权限分配的灵活性
要想最大限度把权限分配变得灵活,角色提供可摘取权限的功能是必不可少的。而针对不同的项目背景,所有的角色和权限也许会出现各种的变化。但其功能还是离不开分配角色和分配权限。
而通过role_privilege表,我们可以在用户登录系统的时候,把该用户角色的权限通过SpringSecurity帮助我们放到用户的权限组内。从而我们可以利用SpringSecurity提供的各种标签,标注访问控制等实现权限功能管理和现实。
例子:
<sec:authorize ifAnyGranted="ROLE_CREATE,ROLE_UPDATE,ROLE_READ,ROLE_DELETE">
<a>用户管理</a>
</sec:authorize>
即用户拥有OLE_CREATE,ROLE_UPDATE,ROLE_READ,ROLE_DELETE任何一个权限的时候才能查看到用户管理按钮。
点进去之后,我们可以再细分对应的权限操作,没有的权限则该功能模块会不出现。
2.3.3、权限的包含关系
有的时候,权限还必须有“包含”关系,即若你具备了某权限,则另外的权限你也必定会具备。
比方说,有个角色他有删除用户的权限,但他没有读取用户的权限。这样觉得有没有问题呢?
若用户没有读取用户的权限,连列表都不出来,那他如何实现删除?这样看上去虽然不是系统上的问题。但一个完善的系统,必须去考虑这样的情况发生。
2.3.4、自定义UserDetailsService接口实现类
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import cn.com.timekey.drugmonitor.business.PrivilegeBus;
import cn.com.timekey.drugmonitor.business.UserBus;
import cn.com.timekey.drugmonitor.log.Log;
import cn.com.timekey.drugmonitor.log.LogFactory;
import cn.com.timekey.drugmonitor.po.Privilege;
import cn.com.timekey.drugmonitor.po.Role;
import cn.com.timekey.drugmonitor.po.RolePrivilege;
import cn.com.timekey.drugmonitor.po.Users;
/**
* @author Kenny
*/
public class MyUserDetailsService implements UserDetailsService {
private static final Log LOGGER = LogFactory
.getLog(MyUserDetailsService.class);
private static final String SYSTEM_ROLE_ID = "1";// 系统默认管理员的id
private UserBus userBus;
private PrivilegeBus privilegeBus;
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
if (StringUtils.isBlank(username)) {
throw new UsernameNotFoundException("no such user.", username);
}
Users user = userBus.findByName(username);
if (user == null) {
LOGGER.debug("no such user by " + username);
throw new UsernameNotFoundException("no such user.", username);
} else if (user.getRole() == null) {
LOGGER.debug("no such role by " + username);
throw new UsernameNotFoundException("no such user.", username);
}
String adminName = user.getUserName();
String password = user.getUserPassword();
Role role = user.getRole();
@SuppressWarnings("unchecked")
Collection<Privilege> privileges = CollectionUtils.EMPTY_COLLECTION;
// 判断是否为系统默认管理员,若是,则直接获取privilege表中全部权限。
if (StringUtils.equals(role.getRoleId(), SYSTEM_ROLE_ID)) {
privileges = privilegeBus.findAll();
}
Set<RolePrivilege> rolePrivileges = role.getRolePrivileges();
@SuppressWarnings("unchecked")
Collection<GrantedAuthority> authorities = CollectionUtils.EMPTY_COLLECTION;
if (privileges.isEmpty() && rolePrivileges != null
&& !rolePrivileges.isEmpty()) {
privileges = new ArrayList<Privilege>(rolePrivileges.size());
for (RolePrivilege rolePrivilege : rolePrivileges) {
privileges.add(rolePrivilege.getPrivilege());
}
}
if (privileges.isEmpty()) {
LOGGER.warn("user has not any rolePrivileges.");
throw new UsernameNotFoundException("Privilege fail! ", username);
}
// 构造权限组
authorities = generateAuthorities(privileges);
boolean isEnable = user.getIsActive();// 如果账号有状态的话,可根据查询结果配置该值。
return new org.springframework.security.core.userdetails.User(
adminName, password, isEnable, true, true, true, authorities);
}
/**
* 构造权限组
*
* @param rolePrivileges
* @return
*/
private Collection<GrantedAuthority> generateAuthorities(
Collection<Privilege> privileges) {
List<GrantedAuthority> auth = new ArrayList<GrantedAuthority>(
privileges.size());
for (Privilege rolePrivilege : privileges) {
GrantedAuthority authority = new GrantedAuthorityImpl(
rolePrivilege.getPrivilegeName());
auth.add(authority);
}
return auth;
}
public void setUserBus(UserBus userBus) {
this.userBus = userBus;
}
public void setPrivilegeBus(PrivilegeBus privilegeBus) {
this.privilegeBus = privilegeBus;
}
}
2.3.5、系统的权限漏洞
出来页面上使用TAG来实现基本的权限功能隐藏与显示外。还必须注意系统内部的权限判断。
使用拦截器保护限制资源
TAG帮我们隐藏了功能的URL,但该URL还是存在的,只要对方知道URL就能直接发请求过来了,从而绕过了权限管理。
我们可以使用拦截器进一步处理请求权限的问题。具体可以在<http auto-config>代码块中配置,如:
<intercept-url pattern="/createUser.do" access="ROLE_USER_CREATE" />
<intercept-url pattern="/listUser.do" access="ROLE_USER_READ" />
<intercept-url pattern="/**" access="ROLE_LOGIN" />
解释:
访问/createUser.do资源必须有ROLE_USER_CREATE权限。
访问/listUser.do资源必须有ROLE_USER_READ。
访问任何资源都必须有ROLE_LOGIN才行。(也可以用IS_AUTHENTICATED_REMEMBERED)
使用标注保护方法调用
有的时候,程序员在编码中会出现疏忽,导致引用错方法。或者在编码时,没有考虑到权限的问题造成一些跨权限的漏洞。
比方说,某个功能因为疏忽,没在拦截器上配置权限拦截,或者功能定义了两个URL入口,而只有其中一个在拦截器上配置了(一个也许是系统旧的遗留入口)。
这样的情况下就会带来权限漏洞,有不良目的人就可以使用这些漏洞来攻击系统,但最重要的还是造成客户损失。
要更进一步的加强“保险”,我们还可以使用标注在代码里面声明拥有某种权限才能调用特定的方法(也可以使用AOP声明的方式,但个人更加喜欢标注的形式,但标注的话相对于会硬编码些)。
使用标注时,记得要在添加上下面代码才生效喔!
<global-method-security secured-annotations="enabled">
</global-method-security>
例子如:
import org.springframework.security.access.annotation.Secured;
public interface AccountBusiness {
@Secured("ROLE_USER_CREATE")
public void save(User user);
@Secured("ROLE_USER_DELETE")
public void delete(String id);
}
3、 Gain 我们的收获
我们再不用去考虑系统中不同角色的有什么权限的问题了,因为权限分配十分灵活化。程序员不必纠结不同项目中,什么角色应该具备哪些权限而烦恼了,但我们必须配置好一套完善的权限列表来满足用户的分配需求。虽然不完美,但减少了很多的烦恼。
角色与权限分配的功能由客户或者业务人员自己来决定。我们只要提供好足够满足对方需求的权限范围就可以了。权限缺少的时候,我们可以增加,但这些工作不至于是无用功。
4、 遗留问题
1.用户登录时,必须重新从数据库里面拿角色对应的权限集,资源消耗是否有点多?
就这个问题而言,我是觉得没必要计较这些资源消耗的,因为权限集再怎么多也不会超过50条吧。
而权限管理系统,一般并发量也不会大的了。如果真的纠结这样的消耗,也可以放用static map用来实现角色与权限集的获取,但记得用上观察者模式。因为权限集是可以被修改的,不用观察者的话就会出现得到过期的权限集了。
2.虽然考虑到数据级的权限管理问题,但目前还是没有提供这样的案例。
3.Group用户组还不在此架构范围内。
- 大小: 16.1 KB
- 大小: 90.3 KB
分享到:
相关推荐
本源码为基于SpringBoot和SpringSecurity的RBAC后台权限管理系统设计,共包含535个文件,其中js文件151个,java文件96个,gif图片76张,css文件66个,html文件52个,PNG图片22张,map文件14个,xml文件13个,svg文件...
本项目基于Spring,整合Spring的security模块,实现用户管理和权限控制,是一套较为通用的权限控制功能,主要内容如下: 1.登录,包括“记住我”的功能; 2.加密,存储的密码不采用明文,初始密码1234; 3.拦截器...
在企业应用中,认证和授权是非常重要的一部分内容,业界最出名...由于Spring Boot非常的流行,选择Spring Security做认证和授权的 人越来越多,今天我们就来看看用Spring 和 Spring Security如何实现基于RBAC的权限管理
Spring Security 是一个强大...总结来说,"spring-security-project.zip"提供了一个使用Spring Security实现RBAC权限模型的实例,涵盖了认证、授权、角色和权限的管理,是学习和理解Spring Security安全框架的好材料。
5. **授权控制**:使用 Spring Security 的访问决策管理器(Access Decision Manager)和访问决策投票器(Access Decision Voter)来实现权限检查。例如,使用 `@PreAuthorize` 或 `@PostAuthorize` 注解进行方法...
Spring Security实现RBAC权限管理一简介在企业应用中,认证和授权是非常重要的一部分内容,业界最出名的两个框架就是大名鼎鼎的Shiro和Spring Security。由于Spring Boot非常的流行,选择Spring Security做认证和...
此例子只是实现用户登录及用户操作是否有权限操作的功能(没有实现完整的用户注册、权限管理等等)。 只有基础的3张表分别为用户、角色、权限。用户-角色、角色-权限它们之间是多对多关系,所以得分别添加一个中间...
《基于Spring Security的RBAC权限管理系统详解》 在IT领域,权限管理是系统设计中不可或缺的一部分,特别是对于大型企业级应用来说,权限控制至关重要。本文将深入探讨如何使用Spring Security框架构建一个基于Role...
基于 Spring Cloud Hoxton 、Spring Boot 2.3、 OAuth2 的RBAC权限管理系统 提供对常见容器化支持 Docker、Kubernetes、Rancher2 支持 提供 lambda 、stream api 、webflux 的生产实践 Spring Boot 2.3.0.RELEASE ...
SpringSecurity通过配置访问决策管理器(AccessDecisionManager)和访问决策投票器(AccessDecisionVoter)来实现权限控制。 3. **Role与Permission**:在RBAC模型中,Role是角色,代表了一组权限的集合,...
标题中的“管理系统系列--Pre基于Spring Boot 、Spring Security的RBAC权限管理系统, 做更简洁.zip”表明这是一个关于构建权限管理系统的教程或代码示例,它利用了Spring Boot和Spring Security这两个核心的Java技术...
在本项目中,我们主要探讨的是如何利用Spring Boot和Spring Security构建一个基于RBAC(Role-Based Access Control)的权限管理系统,以实现一个高效且简洁的后台管理平台。下面将详细介绍这个系统的相关知识点。 1...
通过以上步骤,我们可以实现Spring Security基于数据库的权限管理。这不仅允许我们动态地管理用户权限,还能随着业务的增长进行扩展,满足不同级别的安全需求。在实际应用中,还需要考虑安全性、性能和用户体验等多...
这是一款基于SpringBoot+SpringSecurity的RBAC权限管理系统。原本只想着做成基于SpringSecurity的权限管理系统,但随着功能的增加感觉有些刹不住车了,之后可能会往后台管理系统方向发展。无任何重度依赖,非常适合...
通过分析这些代码,你可以理解如何将Spring Security与数据库集成,实现动态权限管理。 总的来说,Spring Security的动态授权功能使得权限管理变得更加灵活和高效。通过对源代码的适当修改,我们可以构建一个完全可...
在"SpringSecurity权限管理开发手册.pdf"和"SpringSecurity权限管理开发手册.pdf.txt"中,你将找到更多关于如何配置和使用SpringSecurity进行权限管理的详细信息,包括配置XML或Java配置、定义访问规则、处理未授权...
youlai-boot 是【有来开源组织】基于Spring Boot 3 + Spring Security 6 + JWT + Mybatis-Plus + Redis + XXL-Job + Vue3 等主流技术栈搭建的前后端分离权限管理系统。 在线预览地址:http://vue3.youlai.tech 后端...
理解并掌握这个项目,你需要熟悉Spring Boot的开发、Spring Cloud微服务架构、OAuth2的授权流程以及RBAC权限模型。同时,对于数据库设计和前端开发基础也有一定的要求。通过深入学习和实践这个项目,你将能够提升在...
另一份“基于RBAC的权限管理系统的实现.pdf”可能是具体实现的技术文档,涵盖了如何利用Java框架(如Spring Security)实现RBAC模型,以及如何处理权限的动态变更等。 在系统实现过程中,还需要考虑以下几个关键点...
# 基于Spring Cloud Alibaba全家桶的RBAC权限管理系统 ## 项目简介 本项目是一个基于Spring Cloud Alibaba全家桶的RBAC(RoleBased Access Control,基于角色的访问控制)权限管理系统。系统采用Spring Security...