Shiro自定义拦截器实现权限或

阅读Shiro的文档可以知道,Shiro提供的多个权限相关的验证方法只有and关系,而没有提供or的校验方法,也就是说并不支持拥有多个权限中的某一个就验证成功的情景。

Shiro的AccessControlFilter提供了访问控制的基础功能,其中提供的isAccessAllowed方法的返回值表示了是否允许访问。打开他的继承关系可以看到:

AuthenticationFilter和AuthorizationFilter下的实现类都对这个方法提供了实现。前者是认证过滤器,后者是授权过滤器。显然我们应该关注后者的实现方法。我们查看后者PermissionsAuthorizationFilter的实现:

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

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

        boolean isPermitted = true;
        if (perms != null && perms.length > 0) {
            if (perms.length == 1) {
                if (!subject.isPermitted(perms[0])) {
                    isPermitted = false;
                }
            } else {
                if (!subject.isPermittedAll(perms)) {
                    isPermitted = false;
                }
            }
        }

        return isPermitted;
    }

其中isAccessAllowed方法的参数mappedValue就是[urls]配置中拦截器参数部分,也就是我们配置的权限表达式的值,要实现多个权限下“或”的匹配规则,我们只需要自定义一个过滤器,去仿照着重写这个方法即可,我们对应shiro本身规则的“,”,增加“|”来表示or,同时考虑保留shiro本身支持的“,”逗号表示匹配多个权限and的规则,代码如下:

public class CustomAuthorizationFilter extends PermissionsAuthorizationFilter{
	
	//保留shiro原有的“,”分隔and的校验规则,新增“|”分隔的规则
	@Override
    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
        Subject subject = this.getSubject(request, response);
        String[] perms = (String[]) mappedValue;
        boolean isPermitted = true;
        if (perms != null && perms.length > 0) {
            if (perms.length == 1) {
                if (!isOneOfPermitted(perms[0], subject)) {
                    isPermitted = false;
                }
            } else if (!isAllPermitted(perms,subject)) {
                isPermitted = false;
            }
        }
        return isPermitted;
    }
	
	//权限表达式","分隔,and的校验规则
    private boolean isAllPermitted(String[] permStrArray, Subject subject) {
        boolean isPermitted = true;
        for (int index = 0, len = permStrArray.length; index < len; index++) {
            if (!isOneOfPermitted(permStrArray[index], subject)) {
                isPermitted = false;
            }
        }
        return isPermitted;
    }
  //权限表达式"|"分隔,or的校验规则
    private boolean isOneOfPermitted(String permStr, Subject subject) {
        boolean isPermitted = false;
        String[] permArr = permStr.split("\\|");
        if (permArr.length > 0) {
            for (int index = 0, len = permArr.length; index < len; index++) {
                if (subject.isPermitted(permArr[index])) {
                    isPermitted = true;
                }
            }
        }
        return isPermitted;
    }
}

最后还要将自定义的过滤器加入到shiroFilter中:

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean" depends-on="orFilter">
		<property name="securityManager" ref="securityManager" />
		<property name="filters">
	    	<map>
	    	    <entry key="perms" value-ref="orFilter"/>
	    	</map>
	    </property>
	</bean>
	
	<!-- 自定义的过滤器 -->
	<bean id="orFilter" class="com.default.CustomAuthorizationFilter" />

     map中key的值perms不可以更改,这样就实现了满足多个权限中的一个就验证通过的需求。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值