shiro细粒度资源访问控制
【摘要】 细粒度资源访问控制是 Shiro 的核心功能之一,允许开发者基于资源实例(如数据库记录、文件路径等)和操作(如读取、编辑、删除)定义权限。以下是完整的实现步骤和示例代码: 1. 核心概念权限字符串格式:资源:操作(如 user:edit:123 表示编辑 ID 为 123 的用户)授权流程:通过 Subject.isPermitted("权限字符串") 动态判断权限。 2. 完整实现步骤 (...
细粒度资源访问控制是 Shiro 的核心功能之一,允许开发者基于资源实例(如数据库记录、文件路径等)和操作(如读取、编辑、删除)定义权限。以下是完整的实现步骤和示例代码:
1. 核心概念
- 权限字符串格式:
资源:操作
(如user:edit:123
表示编辑 ID 为 123 的用户) - 授权流程:通过
Subject.isPermitted("权限字符串")
动态判断权限。
2. 完整实现步骤
(1) 自定义 Realm 实现权限校验
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 java.util.HashSet;
import java.util.Set;
public class PermissionRealm extends AuthorizingRealm {
// 模拟数据库存储的用户角色和权限
private static final Map<String, Set<String>> USER_ROLES = new HashMap<>();
private static final Map<String, Set<String>> ROLE_PERMISSIONS = new HashMap<>();
static {
// 初始化角色和权限数据
Set<String> adminPermissions = new HashSet<>();
adminPermissions.add("user:create");
adminPermissions.add("user:edit:123"); // 允许编辑ID为123的用户
adminPermissions.add("user:delete");
ROLE_PERMISSIONS.put("admin", adminPermissions);
Set<String> userPermissions = new HashSet<>();
userPermissions.add("user:view");
ROLE_PERMISSIONS.put("user", userPermissions);
USER_ROLES.put("admin", new HashSet<>(Collections.singletonList("admin")));
USER_ROLES.put("user1", new HashSet<>(Arrays.asList("user", "guest")));
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 模拟从数据库获取用户信息
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
String username = upToken.getUsername();
if (!"admin".equals(username) && !"user1".equals(username)) {
throw new UnknownAccountException("用户不存在");
}
return new SimpleAuthenticationInfo(username, "password", getName());
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String username = (String) principals.getPrimaryPrincipal();
Set<String> roles = USER_ROLES.get(username);
if (roles == null) {
return null;
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addRoles(roles);
// 根据角色添加权限
for (String role : roles) {
Set<String> permissions = ROLE_PERMISSIONS.get(role);
if (permissions != null) {
info.addStringPermissions(permissions);
}
}
return info;
}
}
(2) 配置 Shiro 使用自定义 Realm
shiro.ini
配置文件:
[main]
permissionRealm = com.example.PermissionRealm
securityManager.realms = $permissionRealm
(3) 测试细粒度权限校验
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
public class PermissionDemo {
public static void main(String[] args) {
// 初始化 SecurityManager
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
// 获取当前用户
Subject currentUser = SecurityUtils.getSubject();
// 模拟用户登录
currentUser.login(new org.apache.shiro.authc.UsernamePasswordToken("admin", "password"));
// 测试细粒度权限
System.out.println("是否有创建用户权限: " + currentUser.isPermitted("user:create")); // true
System.out.println("是否有编辑ID为123的用户权限: " + currentUser.isPermitted("user:edit:123")); // true
System.out.println("是否有删除用户权限: " + currentUser.isPermitted("user:delete")); // true
System.out.println("是否有编辑ID为456的用户权限: " + currentUser.isPermitted("user:edit:456")); // false(未授权)
// 模拟普通用户登录
currentUser.logout();
currentUser.login(new org.apache.shiro.authc.UsernamePasswordToken("user1", "password"));
System.out.println("普通用户是否有编辑权限: " + currentUser.isPermitted("user:edit:123")); // false
}
}
3. 关键点说明
-
权限字符串设计:
user:create
:全局用户创建权限。user:edit:123
:仅允许编辑 ID 为 123 的用户,实现实例级控制。
-
动态权限校验:
- 通过
Subject.isPermitted("权限字符串")
动态判断,无需硬编码权限逻辑。
- 通过
-
扩展性:
- 可从数据库加载权限数据,支持动态权限变更。
4. 输出结果
运行 PermissionDemo
的输出:
是否有创建用户权限: true
是否有编辑ID为123的用户权限: true
是否有删除用户权限: true
是否有编辑ID为456的用户权限: false
普通用户是否有编辑权限: false
总结
通过自定义 Realm 和权限字符串设计,Shiro 可以轻松实现细粒度资源访问控制。关键点包括:
- 权限字符串格式化:用
资源:操作:实例
定义权限。 - 动态校验:通过
Subject.isPermitted()
实时判断权限。 - 数据驱动:权限数据可从数据库动态加载,适应复杂业务场景。
这种设计既灵活又安全,适用于企业级应用中的权限管理需求。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)