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

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


        
        
            
            /js/** = anon
            /css/** = anon
            /img/** = anon
            /fonts/** = anon
            /scripts/** = anon


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

            
            /backstage/** = perms[admin:*]

            /user/** = user
        
    

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

首先看原来的配置


		
		
		
		    
               
                 
               
        
		
			
				/resources/** = anon
			
		
很明显要想扩展代码,首先要看 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 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的类为自定义类即可


	
		
		
		
		    
               
                 
               
        
		
			
				/resources/** = anon
			
		
	
就这么简单,动态权限控制就完成了

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

你可能感兴趣的:(shiro)