shiro的OGNL 授权策略
【摘要】 Shiro 的 OGNL (Object-Graph Navigation Language) 授权策略是一种高级的权限控制方式,允许开发者通过表达式语言定义复杂的权限规则。OGNL 表达式可以访问 Java 对象的方法和属性,从而动态判断权限。 1. OGNL 授权策略概述作用:通过 OGNL 表达式定义权限条件,例如 user.age > 18 或 resource.owner == c...
Shiro 的 OGNL (Object-Graph Navigation Language) 授权策略是一种高级的权限控制方式,允许开发者通过表达式语言定义复杂的权限规则。OGNL 表达式可以访问 Java 对象的方法和属性,从而动态判断权限。
1. OGNL 授权策略概述
- 作用:通过 OGNL 表达式定义权限条件,例如
user.age > 18
或resource.owner == currentUser
。 - 使用场景:需要基于对象属性或业务逻辑动态判断权限时。
2. 实现步骤
(1) 自定义 Realm 支持 OGNL 表达式
在 doGetAuthorizationInfo
方法中返回 OGNL 表达式对应的权限信息。
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.Collections;
import java.util.HashSet;
import java.util.Set;
public class OgnlPermissionRealm extends AuthorizingRealm {
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 模拟从数据库获取用户信息
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
String username = upToken.getUsername();
if (!"admin".equals(username)) {
throw new UnknownAccountException("用户不存在");
}
return new SimpleAuthenticationInfo(username, "password", getName());
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 添加一个 OGNL 表达式权限
info.addObjectPermission(new WildcardPermission("user:edit:[id]"));
return info;
}
}
(2) 配置 Shiro 使用自定义 Realm
shiro.ini
配置文件:
[main]
ognlPermissionRealm = com.example.OgnlPermissionRealm
securityManager.realms = $ognlPermissionRealm
(3) 自定义 PermissionResolver 解析 OGNL 表达式
实现 PermissionResolver
接口,解析 OGNL 表达式。
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.permission.PermissionResolver;
import org.apache.shiro.authz.permission.WildcardPermission;
public class OgnlPermissionResolver implements PermissionResolver {
@Override
public Permission resolvePermission(String permissionString) {
// 解析 OGNL 表达式
if (permissionString.startsWith("user:edit:")) {
return new OgnlPermission(permissionString);
}
return new WildcardPermission(permissionString);
}
}
(4) 自定义 Permission 类
import org.apache.shiro.authz.Permission;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.StringUtils;
public class OgnlPermission implements Permission {
private final String permissionString;
public OgnlPermission(String permissionString) {
this.permissionString = permissionString;
}
@Override
public boolean implies(Subject subject, Permission permission) {
// 实现 OGNL 表达式逻辑
if (permission instanceof OgnlPermission) {
String otherPermission = ((OgnlPermission) permission).getPermissionString();
// 示例:解析 ID 并比较
if (otherPermission.startsWith("user:edit:")) {
String id = StringUtils.substringAfter(otherPermission, "user:edit:");
// 假设从上下文中获取当前用户和资源 ID
// 这里简化逻辑,直接返回 true(实际需根据业务实现)
return true;
}
}
return false;
}
public String getPermissionString() {
return permissionString;
}
}
(5) 测试 OGNL 权限
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 OgnlPermissionDemo {
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 UsernamePasswordToken("admin", "password"));
// 测试 OGNL 权限
boolean hasPermission = currentUser.isPermitted("user:edit:123");
System.out.println("是否有编辑ID为123的用户权限: " + hasPermission); // true
}
}
3. 关键点说明
-
OGNL 表达式解析:
- 通过
PermissionResolver
解析自定义的 OGNL 表达式。 - 在
implies
方法中实现具体的业务逻辑。
- 通过
-
动态权限判断:
- 权限字符串可以包含变量(如
[id]
),在运行时动态解析。
- 权限字符串可以包含变量(如
-
扩展性:
- 可以结合上下文信息(如当前用户、资源实例)实现复杂权限逻辑。
4. 总结
Shiro 的 OGNL 授权策略提供了一种灵活的方式来实现细粒度的权限控制,特别适合需要动态解析权限表达式的场景。通过自定义 PermissionResolver
和 Permission
类,可以轻松扩展 Shiro 的权限系统以满足业务需求。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)