shiro学习--从数据库获取动态权限

新项目集成了shiro,但是发现原生的只支持在配置文件配置权限,就像这样

<property name="filterChainDefinitions">
        <!-- , roles[admin], perms[document:read] -->
        <value>
            <!-- 对静态资源设置匿名访问 -->
            /js/** = anon
            /css/** = anon
            /img/** = anon
            /fonts/** = anon
            /scripts/** = anon


            /user/login.action = authc
            /user/logout = logout

            <!-- 进入后台需要权限:admin:* -->
            /backstage/** = perms[admin:*]

            /user/** = user
        </value>
    </property>

可是,正常项目的权限不可能是静态的,一般都是从数据库获取的动态权限数据,如果使用配置文件,每次权限改动都要修改配置文件,然后重启服务器,这显然不是我们想要的,所以只能对shiro框架进行扩展,下面是我自己的一些思路和代码

首先看原来的配置

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<property name="securityManager" ref="securityManager" />
		<property name="loginUrl" value="${shiro.login.page.url}" />
		<property name="unauthorizedUrl" value="${shiro.unauthorized.url}" />
		<property name="filters">    
           <map>    
               <entry key="myPermissionFilter" value-ref="myPermissionFilter"/>  
           </map>    
        </property>
		<property name="filterChainDefinitions">
			<value>
				/resources/** = anon
			</value>
		</property>
</bean>
很明显要想扩展代码,首先要看 org.apache.shiro.spring.web.ShiroFilterFactoryBean中的给filterChainDefinitions赋值的setFilterChainDefinitions(String definitions)方法源码

public void setFilterChainDefinitions(String definitions) {
        Ini ini = new Ini();
        ini.load(definitions);
        //did they explicitly state a 'urls' section?  Not necessary, but just in case:
        Ini.Section section = ini.getSection(IniFilterChainResolverFactory.URLS);
        if (CollectionUtils.isEmpty(section)) {
            //no urls section.  Since this _is_ a urls chain definition property, just assume the
            //default section contains only the definitions:
            section = ini.getSection(Ini.DEFAULT_SECTION_NAME);
        }
        setFilterChainDefinitionMap(section);
    }

看到源码发现很简单definitions参数就是配置的字符串,方法里的源码就是把配置字符串转换成shiro需要的数据,具体的过程我们不需要关心,我们只需要在definitions上“动手脚”就可以了,具体怎么做?最简单的是从数据库读取出权限列表然后字符串拼接即可

有了思路,那么就写一个继承于ShiroFilterFactoryBean类的子类ShiroPermissionFactory,重写setFilterChainDefinitions(String definitions)方法即可

public class ShiroPermissionFactory extends ShiroFilterFactoryBean {
	
	/**配置中的过滤链*/
	public static String definitions;
	
	/**权限service*/
	@Autowired
	private ShiroPermissionsService permissionsService;

	/**
	 * 从数据库动态读取权限
	 */
	@Override
	public void setFilterChainDefinitions(String definitions) {
		ShiroPermissionFactory.definitions = definitions;
		
        //数据库动态权限
        List<PermissionsPo> permissions = permissionsService.findAll();
        for(PermissionsPo po : permissions){
        	//字符串拼接权限
        	definitions = definitions+po.getUrl() + " = "+"perms["+po.getId()+"]";
        }
        
		//从配置文件加载权限配置
		Ini ini = new Ini();
        ini.load(definitions);
        Ini.Section section = ini.getSection(IniFilterChainResolverFactory.URLS);
        if (CollectionUtils.isEmpty(section)) {
            section = ini.getSection(Ini.DEFAULT_SECTION_NAME);
        }
        
        //加入权限集合
        setFilterChainDefinitionMap(section);
	}
}
然后在配置文件配置bean的类为自定义类即可

<!-- 使用自定义的Shiro Web过滤器 -->
	<bean id="shiroFilter" class="com.longmap.passport.shiro.ShiroPermissionFactory">
		<property name="securityManager" ref="securityManager" />
		<property name="loginUrl" value="${shiro.login.page.url}" />
		<property name="unauthorizedUrl" value="${shiro.unauthorized.url}" />
		<property name="filters">    
           <map>    
               <entry key="myPermissionFilter" value-ref="myPermissionFilter"/>  
           </map>    
        </property>
		<property name="filterChainDefinitions">
			<value>
				/resources/** = anon
			</value>
		</property>
	</bean>
就这么简单,动态权限控制就完成了

PS:要记住在增删改权限数据库时记得调用setFilterChainDefinitions()方法重新加载

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值