shiro的OGNL 授权策略

举报
林欣 发表于 2025/05/25 23:30:29 2025/05/25
【摘要】 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 > 18resource.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. 关键点说明

  1. OGNL 表达式解析

    • 通过 PermissionResolver 解析自定义的 OGNL 表达式。
    • implies 方法中实现具体的业务逻辑。
  2. 动态权限判断

    • 权限字符串可以包含变量(如 [id]),在运行时动态解析。
  3. 扩展性

    • 可以结合上下文信息(如当前用户、资源实例)实现复杂权限逻辑。

4. 总结

Shiro 的 OGNL 授权策略提供了一种灵活的方式来实现细粒度的权限控制,特别适合需要动态解析权限表达式的场景。通过自定义 PermissionResolverPermission 类,可以轻松扩展 Shiro 的权限系统以满足业务需求。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。