若依框架之数据权限的设计和编写
在实际开发中,需要设置用户只能查看哪些部门的数据,这种情况一般称为数据权限。 例如对于销售,财务的数据,它们是非常敏感的,因此要求对数据权限进行控制, 对于基于集团性的应用系统而言,就更多需要控制好各自公司的数据了。如设置只能看本公司、或者本部门的数据,对于特殊的领导,可能需要跨部门的数据, 因此程序不能硬编码那个领导该访问哪些数据,需要进行后台的权限和数据权限的控制。
提示
默认系统管理员
admin
拥有所有数据权限(userId=1)
,默认角色拥有所有数据权限(如不需要数据权限不用设置数据权限操作)
1. 基础依赖导入
首先,我们需要确保项目中的 pom.xml
只包含实现角色管理和 RBAC 权限控制所需的基础依赖。
pom.xml
基础依赖
<dependencies>
<!-- Spring Boot 相关依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- MyBatis 相关依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!-- Shiro 依赖 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.7.0</version>
</dependency>
<!-- MySQL 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
详解
- Spring Boot Starter Web: 提供创建 REST API 和 MVC 应用程序所需的基本功能。
- Spring Boot Starter Data JPA: 提供与数据库进行交互的基本功能,并使用 JPA(Java Persistence API)进行 ORM(对象关系映射)。
- MyBatis Starter: 这是 MyBatis 的 Spring Boot Starter,它简化了与数据库的交互,并允许使用传统的 SQL 查询。
- Apache Shiro: 用于实现安全框架,提供了身份验证、授权、加密等安全功能。
- MySQL Connector: MySQL 的 JDBC 驱动程序,用于连接和操作 MySQL 数据库。
2. 配置文件
在 application.yml
或 application.properties
中配置数据库连接和 Shiro 相关的设置。
application.yml
yaml复制代码spring:
datasource:
url: jdbc:mysql://localhost:3306/rbac_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: root
password: yourpassword
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/**/*.xml
type-aliases-package: com.example.rbac.domain
shiro:
user:
login-url: /login
success-url: /index
unauthorized-url: /403
详解
- spring.datasource: 定义数据库连接参数,包括连接 URL、用户名、密码和驱动程序类名。
- mybatis.mapper-locations: 指定 MyBatis Mapper XML 文件的位置。
- mybatis.type-aliases-package: 指定 MyBatis 使用的实体类所在的包。
- shiro.user.login-url: Shiro 登录 URL。
- shiro.user.success-url: 登录成功后重定向的 URL。
- shiro.user.unauthorized-url: 未授权时重定向的 URL。
3. 数据库表结构设计
我们将设计三个核心表,用于实现 RBAC 权限控制:
- 用户表 (
sys_user
): 存储用户的基本信息。 - 角色表 (
sys_role
): 存储角色的基本信息。 - 用户-角色关联表 (
sys_user_role
): 存储用户与角色的关联关系。
此外,我们还会创建权限表和角色-权限关联表来支持更细粒度的权限控制。
sys_user
表
sql复制代码CREATE TABLE sys_user (
user_id BIGINT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(100) NOT NULL,
salt VARCHAR(50) NOT NULL,
status TINYINT(1) DEFAULT 1,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
详解
- user_id: 用户的唯一标识。
- username: 用户的登录名,唯一。
- password: 加密存储的密码。
- salt: 密码加密时使用的盐值,用于增强安全性。
- status: 用户状态(例如,1 表示启用,0 表示禁用)。
- create_time 和 update_time: 自动记录创建和更新的时间。
sys_role
表
sql复制代码CREATE TABLE sys_role (
role_id BIGINT PRIMARY KEY AUTO_INCREMENT,
role_name VARCHAR(50) NOT NULL UNIQUE,
role_key VARCHAR(50) NOT NULL UNIQUE,
status TINYINT(1) DEFAULT 1,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
详解
- role_id: 角色的唯一标识。
- role_name: 角色名称(例如,管理员、普通用户)。
- role_key: 角色标识,用于程序内部引用。
- status: 角色状态(例如,1 表示启用,0 表示禁用)。
- create_time 和 update_time: 记录创建和更新的时间。
sys_user_role
表
sql复制代码CREATE TABLE sys_user_role (
user_id BIGINT NOT NULL,
role_id BIGINT NOT NULL,
PRIMARY KEY (user_id, role_id),
FOREIGN KEY (user_id) REFERENCES sys_user(user_id) ON DELETE CASCADE,
FOREIGN KEY (role_id) REFERENCES sys_role(role_id) ON DELETE CASCADE
);
详解
- user_id: 关联到
sys_user
表的用户标识。 - role_id: 关联到
sys_role
表的角色标识。 - PRIMARY KEY: 复合主键,确保每个用户-角色组合唯一。
- FOREIGN KEY: 外键约束,确保用户和角色存在,并在删除用户或角色时自动删除关联记录。
4. 数据库表结构扩展(权限相关表)
为了支持更细粒度的权限控制,我们还需要创建权限表和角色-权限关联表:
sys_permission
表
sql复制代码CREATE TABLE sys_permission (
permission_id BIGINT PRIMARY KEY AUTO_INCREMENT,
permission_name VARCHAR(50) NOT NULL UNIQUE,
permission_key VARCHAR(50) NOT NULL UNIQUE,
status TINYINT(1) DEFAULT 1,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
详解
- permission_id: 权限的唯一标识。
- permission_name: 权限名称(例如,查看用户、编辑用户)。
- permission_key: 权限标识,用于程序内部引用。
- status: 权限状态(例如,1 表示启用,0 表示禁用)。
- create_time 和 update_time: 记录创建和更新的时间。
sys_role_permission
表
sql复制代码CREATE TABLE sys_role_permission (
role_id BIGINT NOT NULL,
permission_id BIGINT NOT NULL,
PRIMARY KEY (role_id, permission_id),
FOREIGN KEY (role_id) REFERENCES sys_role(role_id) ON DELETE CASCADE,
FOREIGN KEY (permission_id) REFERENCES sys_permission(permission_id) ON DELETE CASCADE
);
详解
- role_id: 关联到
sys_role
表的角色标识。 - permission_id: 关联到
sys_permission
表的权限标识。 - PRIMARY KEY: 复合主键,确保每个角色-权限组合唯一。
- FOREIGN KEY: 外键约束,确保角色和权限存在,并在删除角色或权限时自动删除关联记录。
总体思路:
1.总共有五个表:用户表,角色表,用户角色关联表,角色权限关联表,权限表
2.用户如何拿到一个权限呢?
3.通过用户Id去查询用户角色关联表,可以得到该用户所拥有的角色Id,这个可以是一对多的关系,即一个用户可以拥有多个角色。
4.根据查询出来的角色id去查询角色权限关联表,可以得到拥有的权限id,当然这也是一对多的关系,所以一个角色就可以拥有多个权限。
5.最后根据权限id去查询权限表,这样就可以得到所拥有的权限了
这样设计的好处:
符合了RBAC原则
1. 灵活性和可扩展性
- 多对多关系:通过中间关联表(用户角色关联表和角色权限关联表),实现了用户与角色、角色与权限之间的多对多关系。这种设计允许一个用户拥有多个角色,一个角色也可以拥有多个权限,反之亦然,从而提供了更大的灵活性。
- 易于扩展:当需要添加新角色或权限时,只需在相关的角色表或权限表中添加记录,并在关联表中建立关联即可,无需修改已有结构。
2. 权限管理简化
- 角色分配:将权限与角色进行绑定后,可以通过为用户分配角色来间接赋予权限,这简化了权限的管理,尤其是当多个用户需要相同的权限时,只需赋予他们相同的角色即可。
- 权限继承:在需要修改某一类用户的权限时,只需调整角色与权限的关联即可,所有拥有该角色的用户都会立即生效。
3. 数据库查询效率
- 分级查询:通过多次查询获取权限信息,这种设计有助于减少单次查询的复杂度,且每次查询都基于索引优化,可以提高查询效率。
用户如何获取权限
- 通过用户ID查询用户角色关联表:首先,根据用户的ID从
用户角色关联表
中查询出该用户所拥有的所有角色ID。 - 根据角色ID查询角色权限关联表:接下来,通过这些角色ID在
角色权限关联表
中查询对应的权限ID。 - 根据权限ID查询权限表:最后,根据权限ID从
权限表
中查询出具体的权限信息。
总结
这种设计将用户、角色和权限分离开来,通过中间表实现多对多关联,既提高了系统的灵活性和可扩展性,又简化了权限的管理和维护工作,是一种常见且有效的RBAC实现方式。
RBAC原则:
RBAC(基于角色的访问控制,Role-Based Access Control)的基本原则主要围绕角色、权限、用户之间的关系进行管理和控制,具体原则如下:
1. 最小权限原则(Principle of Least Privilege)
- 描述:每个用户应该只被授予完成其工作所需的最低权限。
- 目的:防止用户获取超过其职责范围的权限,从而减少潜在的安全风险。
2. 职责分离原则(Separation of Duties)
- 描述:通过将特定权限分配给不同的角色,确保一个用户不能同时完成所有关键任务,从而防止欺诈或错误行为。
- 目的:确保重要操作需要多个角色协作完成,避免单点故障或恶意行为。
3. 权限与角色分离原则(Role-Permission Separation)
- 描述:权限应与角色分离,而不直接与用户绑定,用户通过其角色获得权限。
- 目的:简化权限管理,通过角色的权限配置来间接控制用户的权限,方便统一管理和维护。
4. 角色继承原则(Role Hierarchy Principle)
- 描述:角色可以有继承关系,较高层级的角色可以继承低层级角色的权限。
- 目的:简化角色的管理,使得一些通用权限可以通过角色继承而共享。
5. 角色互斥原则(Mutually Exclusive Roles)
- 描述:某些角色之间是互斥的,某个用户不能同时拥有这类互斥的角色,以防止冲突或滥用。
- 目的:避免因为角色之间的冲突导致权限管理混乱或出现安全漏洞。
6. 最小角色原则(Principle of Least Role)
- 描述:每个用户应当只被赋予其当前任务所需的最少数量的角色。
- 目的:进一步细化权限控制,确保用户不因拥有过多角色而获得不必要的权限。
7. 基于角色的权限聚合(Permission Aggregation Based on Roles)
- 描述:权限不应直接分配给用户,而应聚合到角色中,用户通过角色获得权限。
- 目的:使权限分配和管理更有条理,便于系统的权限架构设计和优化。
8. 临时角色原则(Temporary Roles Principle)
- 描述:有些角色可以是临时的,用户在特定时间段或任务期间拥有这些角色,任务完成后角色会被撤销。
- 目的:减少长期暴露在系统中的权限,降低风险。
总结
RBAC原则确保了权限管理的有效性和安全性,通过合理配置角色和权限,RBAC可以帮助组织实现更安全、更精细化的访问控制,符合安全管理和合规性要求。
具体代码实现:
通过shiro框架的认证和授权协议
拥有什么权限访问什么数据!
注意:巨多坑!!!
1.shiro框架要实现授权必须是在登录的情况下
2.授权的配置规则必须在认证规则上面,不然会重定向
3.一定要写登陆页面,拦截会跳转到登录页面!
4.登录的请求要给通过,不需要拦截,即给游客身份
5.授权必须是perms[a:b]这样的格式,不然会出错!
必须必须是 元素一:元素二这样的格式!!! 必须有冒号!
注意点配置大概如下:
//
filterChainDefinitionMap.put("/login","anon");//放过登录的请求
//授权拦截规则必须在认证拦截上面定义,不然授权会被重定向到登录页面 大坑!!!
filterChainDefinitionMap.put("/test/find","perms[View:Users]"); //认证了的用户才可以授权!!! 切记
filterChainDefinitionMap.put("/**", "authc"); //拦截其他的请求
具体实现:
1.导入依赖
版本不行就往下降!!!
<!-- Shiro 依赖 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.7.0</version>
</dependency>
2.编写配置类
一个Realm类:
package com.example.ruoyirbac.config;
import com.example.ruoyirbac.mapper.SysPermissionMapper;
import com.example.ruoyirbac.pojo.*;
import com.example.ruoyirbac.service.SysRolePermissionService;
import com.example.ruoyirbac.service.SysRoleService;
import com.example.ruoyirbac.service.SysUserRoleService;
import com.example.ruoyirbac.service.SysUserService;
import org.apache.catalina.User;
import org.apache.catalina.realm.AuthenticatedUserRealm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
public class UserRealm extends AuthorizingRealm {
@Autowired
SysUserService service;
@Autowired
SysRoleService roleService;
@Autowired
SysUserRoleService userRoleService;
@Autowired
SysRolePermissionService rolePermissionService;
@Autowired
SysPermissionMapper mapper;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("进入授权");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// // 获取当前登录的用户对象
// Subject subject = SecurityUtils.getSubject();// 获取对象
//
// // 从用户对象中获取认证时传递过来的用户信息(User对象)
// SysUser principal = (SysUser) subject.getPrincipal();//接收认证传过来的对象
//
// System.out.println("获取到的用户是:"+principal);
//
// //根据用户查询用户角色表的到角色ID
//
// SysUserRole sysUserRole = userRoleService.selectById(principal.getUser_id());
//
// System.out.println("角色ID为:"+sysUserRole.getRoleId());
//
// //根据角色ID和角色权限表获取权限ID
//
// SysRolePermission sysRolePermission = rolePermissionService.selectById(sysUserRole.getRoleId());
//
// System.out.println("权限ID为:"+sysRolePermission.getPermissionId());
//
// //根据权限ID获取权限
//
// SysPermission sysPermission = mapper.selectById(sysRolePermission.getPermissionId());
//
// System.out.println("权限为:"+sysPermission);
//
// info.addStringPermission(sysPermission.getPermissionName());
info.addStringPermission("View:Users"); //授权协议
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("进入了认证");
//验证token
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;//强转为用户的认证
SysUser user = service.findByUsername(token.getUsername());
System.out.println(user);
//账号认证自己做
if(user == null)
{
return null;//会自带抛出异常
}
//密码认证,shiro来做
return new SimpleAuthenticationInfo(user,user.getPassword(),""); //把user传递给授权
}
}
config配置类:
package com.example.ruoyirbac.config;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
// 1. 创建一个ShiroFilterFactoryBean的Bean
@Bean
public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 设置SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 定义拦截规则
Map<String, String> filterChainDefinitionMap = new HashMap<>();
//
filterChainDefinitionMap.put("/login","anon");//放过登录的请求
//授权拦截规则必须在认证拦截上面定义,不然授权会被重定向到登录页面 大坑!!!
filterChainDefinitionMap.put("/test/find","perms[View:Users]"); //认证了的用户才可以授权!!! 切记
filterChainDefinitionMap.put("/**", "authc"); //拦截其他的请求
/*
anon(匿名):不需要身份验证即可访问。
authc(身份验证):需要身份验证才能访问。
authcBasic(基本身份验证):需要HTTP基本身份验证才能访问。
user(用户):只有已记住的用户才能访问,或者已经身份验证的用户也可以。
perms(权限):需要指定的权限才能访问。例如:"perms[user:create]" 表示需要user:create权限。
roles(角色):需要指定的角色才能访问。例如:"roles[admin]" 表示需要admin角色。
ssl(SSL):需要SSL连接才能访问。
rest(REST):基于REST风格的URL权限控制,自动根据请求的方法(如GET、POST、DELETE等)进行权限控制。
port(端口):访问的URL的端口必须匹配才允许访问。*/
// 如果需要更复杂的权限控制,可以添加更多规则,例如:
// filterChainDefinitionMap.put("/admin/**", "roles[admin]"); // admin目录下的所有资源需要admin角色
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
// 设置登录页面
shiroFilterFactoryBean.setLoginUrl("/toLogin");
return shiroFilterFactoryBean;
}
// 2. 创建一个DefaultWebSecurityManager的Bean
@Bean(name = "securityManager")
public DefaultWebSecurityManager securityManager(@Qualifier("userRealm") Realm realm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm);
return securityManager;
}
// 3. 定义一个Realm对象
@Bean(name = "userRealm")
public UserRealm userRealm() {
return new UserRealm();
}
// 注意:UserRealm需要您自己实现,并且需要继承org.apache.shiro.realm.AuthorizingRealm
// 在UserRealm中,您需要重写doGetAuthorizationInfo和doGetAuthenticationInfo方法
// 来实现权限和身份验证逻辑
}
登陆控制层编写
@RequestMapping("/login")
public String login(@RequestParam("username")String username,
@RequestParam("password")String password){
Subject currentUser = SecurityUtils.getSubject();
if (!currentUser.isAuthenticated()) {
//如果还未认证,配置token
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
currentUser.login(token);
System.out.println("1");
return "index.html";
}
catch (UnknownAccountException uae)
{
System.out.println("2");
return "login.html"; //错误就返回登录页面
}
catch (IncorrectCredentialsException ice)
{
System.out.println("3");
return "login.html";
}
}
return "index.html"; //正确就进入主页面
}
shiro整合thymeleaf
实现html元素特定角色特定看
在 Thymeleaf 中集成 Shiro,可以通过使用 thymeleaf-extras-shiro
提供的自定义标签来控制页面元素的显示与隐藏。下面是一个示例 HTML 页面,展示了如何使用这些标签。
1. 引入 Thymeleaf Shiro Namespace
首先,在 HTML 页面顶部引入 Shiro 的命名空间:
<html xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
<title>Shiro & Thymeleaf Example</title>
</head>
<body>
2. 使用 Shiro 标签控制页面显示
<!-- 仅认证用户可见 -->
<shiro:authenticated>
<p>Welcome, authenticated user!</p>
</shiro:authenticated>
<!-- 仅未认证用户可见 -->
<shiro:notauthenticated>
<p>Please <a th:href="@{/login}">log in</a>.</p>
</shiro:notauthenticated>
<!-- 用户具有特定角色时可见 -->
<shiro:hasRole name="admin">
<p>You are an administrator.</p>
</shiro:hasRole>
<shiro:lacksRole name="admin">
<p>You are not an administrator.</p>
</shiro:lacksRole>
<!-- 用户具有特定权限时可见 -->
<shiro:hasPermission name="document:read">
<p>You have permission to read documents.</p>
</shiro:hasPermission>
<shiro:lacksPermission name="document:read">
<p>You do not have permission to read documents.</p>
</shiro:lacksPermission>
3. 示例页面内容
综合以上标签,一个完整的示例页面可能如下:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
<title>Shiro & Thymeleaf Example</title>
</head>
<body>
<shiro:authenticated>
<h2>Welcome, authenticated user!</h2>
<p>Thank you for logging in.</p>
<shiro:hasRole name="admin">
<p>You are an administrator.</p>
</shiro:hasRole>
<shiro:hasPermission name="document:read">
<p>You have permission to read documents.</p>
</shiro:hasPermission>
</shiro:authenticated>
<shiro:notauthenticated>
<h2>Welcome, Guest!</h2>
<p>Please <a th:href="@{/login}">log in</a> to access more features.</p>
</shiro:notauthenticated>
</body>
</html>
4. 运行效果
- 如果用户已认证,他们会看到 "Welcome, authenticated user!" 的消息。
- 如果用户具有
admin
角色,他们会看到 "You are an administrator." 的消息。 - 如果用户具有
document:read
权限,他们会看到相应的权限提示。 - 如果用户未认证,则会提示登录信息。
通过这种方式,Shiro 可以与 Thymeleaf 模板很好地结合,提供基于角色和权限的内容控制。
通过Shiro来实现的大致思路
通过Apache Shiro实现RBAC的基本思路如下:
1. 用户认证(Authentication)
- 用户登录:首先通过用户名和密码进行用户身份验证。Shiro会根据用户输入的凭证(通常是用户名和密码)与系统中的信息进行匹配。
- Realm配置:自定义
Realm
,用于从数据库或其他存储中获取用户信息,并实现认证逻辑。
2. 角色授权(Authorization)
- 定义角色和权限:在数据库中设计并存储角色与权限的关系。
- 基于角色的授权:Shiro支持通过角色进行授权,即检查用户是否拥有某个角色,决定其是否可以执行某些操作。
- 基于权限的授权:Shiro也支持更细粒度的授权,即检查用户是否拥有某个具体的权限。
3. 权限控制配置
-
配置文件:在Shiro的配置文件(如
shiro.ini
或Spring配置文件)中,配置URL与角色或权限的映射关系。例如:[urls] /admin/** = roles[admin] /edit/** = perms[edit]
-
注解方式:在代码中使用Shiro的注解(如
@RequiresRoles
或@RequiresPermissions
)来控制方法的访问权限。例如:@RequiresRoles("admin") public void adminMethod() { // 管理员操作 }
4. 权限校验流程
- 用户访问某个资源时,Shiro会根据预先配置好的角色或权限映射,检查当前用户是否具备访问该资源的权限。
- 如果用户没有相应的权限,Shiro将拒绝该请求并返回相应的错误提示(如403 Forbidden)。
5. 会话管理和单点登录
- 会话管理:Shiro提供了会话管理功能,可以管理用户的登录状态、超时处理等。
- 单点登录(SSO):通过Shiro的扩展,支持单点登录功能,使用户在多个系统间无缝切换。
6. 自定义扩展
- 自定义Realm:通过继承Shiro的
AuthorizingRealm
类,可以自定义用户的认证和授权逻辑,支持从数据库或其他存储中动态加载角色和权限。 - 灵活配置:通过Shiro的配置文件或Spring集成,可以灵活配置各种权限控制策略。
总结
通过Shiro实现RBAC,可以充分利用其灵活的认证和授权机制,结合自定义的Realm,实现基于角色的细粒度权限控制,适应不同应用场景的需求。
Leave a reply