自定义Shiro拦截器,实现角色多选一

本文介绍了为何以及如何自定义Shiro的拦截器,以实现更灵活的角色权限管理。通过覆盖默认的拦截器如RolesAuthorizationFilter,并使用自定义的拦截器,可以实现对用户角色的多选一授权。在配置中替换默认拦截器并注意在授权时正确处理Role和Perms的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为什么自定义Shiro的拦截器

Shiro自带的拦截器,一个请求只能赋予一个角色或者一个组合角色。
例如:
filterChainDefinitionMap.put("/user/*","roles[user,admin]");  表示只有同时获得user和admin的角色才能访问/user/*

但是实际中,需要/user/* 的请求user和admin角色都可以访问,那么就需要自定义拦截器

怎么自定义Shiro的拦截器

默认的拦截器

所有的拦截器都继承了AccessControlFilter类

继承了AccessControlFilter类的拦截器有下图中的几种:
在这里插入图片描述

默认使用的拦截器是:RolesAuthorizationFilter

在默认的拦截器中,roles[user,admin] 表示user加上admin的组合角色

    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {

        Subject subject = getSubject(request, response);
        String[] rolesArray = (String[]) mappedValue;

        if (rolesArray == null || rolesArray.length == 0) {
            //no roles specified, so nothing to check - allow access.
            return true;
        }

        Set<String> roles = CollectionUtils.asSet(rolesArray);  //将所有的权限加起来的组合权限
        return subject.hasAllRoles(roles);
    }

CollectionUtils.asSet()方法

    public static <E> Set<E> asSet(E... elements) {
        if (elements == null || elements.length == 0) {
            return Collections.emptySet();
        }

        if (elements.length == 1) {
            return Collections.singleton(elements[0]);
        }

        LinkedHashSet<E> set = new LinkedHashSet<E>(elements.length * 4 / 3 + 1);
        Collections.addAll(set, elements);
        return set;
    }

自定义拦截器

//自定义Shiro过滤器
public class RoleFilter extends RolesAuthorizationFilter {
    @Override
    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
        final Subject subject = getSubject(request, response);
        final String[] rolesArray = (String[]) mappedValue;

        if (rolesArray == null || rolesArray.length == 0) {
            // 无指定角色时,无需检查,允许访问
            return true;
        }

        for (String roleName : rolesArray) {
            if (subject.hasRole(roleName)) {
                return true;
            }
        }
        return false;
    }
}

设置拦截器为自定义的拦截器

@Bean("getShiroFilterFactoryBean")
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(defaultWebSecurityManager);
        //自定义拦截器类型
        //import javax.servlet.Filter;
        Map<String, Filter> filterMap = new LinkedHashMap<>();
        filterMap.put("roles", new RoleFilter());
        //设置拦截器为自定义的拦截器
        bean.setFilters(filterMap);

        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();

        filterChainDefinitionMap.put("/user/*","roles[user,admin]");
        filterChainDefinitionMap.put("/admin/*","roles[admin]");

       // 设置过滤器
        bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        //设置登录的请求  可以是路由也可以是压面
        bean.setLoginUrl("/common/toLogin");
        //设置未授权的请求 未授权-->未授权页面
        bean.setUnauthorizedUrl("/common/toLogin");
        return bean;
    }

注意点

注意自己在授权时 是授予Role还是授予Perms

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获取当前登录对象
        Subject subject = SecurityUtils.getSubject();
        User currentUser = (User) subject.getPrincipal(); //得到当前对象
        //如果当前对象不为空 进行授权操作
        if(currentUser!=null){
            //设置当前用户的权限
            //info.addStringPermission(currentUser.getPerms()); //授予perm
            info.addRole(currentUser.getRole());  //赋予Role
        }
        return info;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值