Shiro教程(十)Shiro 权限动态加载与配置精细讲解

信息发布:soゝso 发布日期:2016-08-26 01:30 热度:2298 分享到:

shiro demo下载

Shiro + SSM(框架) + Freemarker(jsp)讲解的权限控制Demo,还不赶快去下载?

Shiro  是一个很完美的权限控制框架,一般我们会采用 shiro  的标签,在页面判断,从而来判断一些Button Link Tag  的显示与否,但是仅仅这样判断是不够的,如果用户知道链接,这就一点用都没有。所以我们后台还要有一层判断。这样才安全。今天来说说 Shiro  后台判断的这点事。

shiro标签讲解:

Freemarker  使用Shiro 标签的介绍:http://www.sojson.com/blog/143.html

JSP  使用Shiro 标签的介绍:http://www.sojson.com/blog/144.html

shiro一般是这样配置。

<property name="filterChainDefinitions" >
	<value>
		/** = anon
		/page/login.jsp = anon
		/page/register/* = anon
		/page/index.jsp = authc
		/page/addItem* = authc,roles[数据管理员]
		/page/file* = authc,roleOR[普通用户,数据管理员]
		/page/listItems* = authc,roleOR[数据管理员,普通用户]
		/page/showItem* = authc,roleOR[数据管理员,普通用户]
		/page/updateItem*=authc,roles[数据管理员]
    </value>
</property>

这样配置有什么问题?

shiro  加载配置,或者说校验配置,是从上而下的,也就是向上面的配置,其实是有问题的。可能不仔细看你没看出来,/** = anon  ,如果把这个配置在第一行,其实下面的配置都没用。因为是从上往下去匹配,只要匹配中了,就不匹配了,这个是重点,所以要有序

其次,我们知道,这样配置有一个问题,就是维护起来费劲,它不如单独的配置文件,比如我们常用properties 配置文件来配置一些经常修改的值。如:jdbc.properties 会配置一些数据库的链接,帐号、密码等。

说到这里,有的同学就会想,那么我们就用 properties

properties 我们来看看有什么问题?

properties 配置,其实是没问题,问题就出在读取 properties 配置上。我们一般读取,或者说常用读取properties 配置文件,都是用相对应的 Java   JDK   自带提供java.util.Properties 工具类,我们可以看到这个工具类的情况。

public class Properties extends Hashtable<Object,Object> {
	//Do some thing
}

它继承了 Hashtable ,这就是出现了一个问题,Hashtable 是无序的。这就是关键点。

Shiro 权限拦截动态配置方案

1.重写java.util.Properties  工具类 ,继承 LinkedHashMap<K, V>() LinkedHashMap()  是有序的。

2.自己写一个读取文件的工具类也可以解决。

我的实现是用ini配置文件,自己写了一个读取的工具类,已经封装好,欲知详情或者下载请点击:http://www.sojson.com/blog/139.html

里面有工具类的下载,本站的实现,以及本站发布的开源Demo项目:SpringMVC + Mybatis + Shiro + Redis

这个 Demo  里的配置文件:

[base_auth]
/u/**=anon
/user/**=simple,login
/js/**=anon
/css/**=anon 
/open/**=anon

#不用校验地址是否有权限
/permission/selectPermissionById.shtml=simple,login
/member/onlineDetails/**=simple,login
/role/mypermission.shtml=simple,login
/role/getPermissionTree.shtml=simple,login
/role/selectRoleByUserId.shtml=simple,login


#需要根据地址校验有无权限
/permission/**=simple,login,permission
/role/**=simple,login,permission
/member/**=simple,login,permission




/**=simple,login

配置文件加载类:

package com.sojson.core.shiro.service.impl;

import java.io.IOException;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.core.io.ClassPathResource;

import com.sojson.common.utils.LoggerUtils;
import com.sojson.core.config.INI4j;
import com.sojson.core.shiro.service.ShiroManager;
/**
 * 
 * 开发公司:SOJSON在线工具 <p>
 * 版权所有:© www.sojson.com<p>
 * 博客地址:http://www.sojson.com/blog/  <p>
 * <p>
 * 
 * 动态加载权限 Service
 * 
 * <p>
 * 
 * 区分 责任人 日期    说明<br/>
 * 创建 周柏成 2016年6月2日  <br/>
 *
 * @author zhou-baicheng
 * @email  [email protected]
 * @version 1.0,2016年6月2日 <br/>
 * 
 */
public class ShiroManagerImpl implements ShiroManager {
	
	// 注意/r/n前不能有空格
	private static final String CRLF = "\r\n";

	@Resource
	private ShiroFilterFactoryBean shiroFilterFactoryBean;


	@Override
	public String loadFilterChainDefinitions() {
		
		StringBuffer sb = new StringBuffer();
			sb.append(getFixedAuthRule());//固定权限,采用读取配置文件
		return sb.toString();
	}
	
	/**
	 * 从配额文件获取固定权限验证规则串
	 */
	private String getFixedAuthRule(){
		String fileName = "shiro_base_auth.ini";
		ClassPathResource cp = new ClassPathResource(fileName);
		INI4j ini = null;
		try {
			ini = new INI4j(cp.getFile());
		} catch (IOException e) {
			LoggerUtils.fmtError(getClass(), e, "加载文件出错。file:[%s]", fileName);
		}
		String section = "base_auth";
		Set<String> keys = ini.get(section).keySet();
		StringBuffer sb = new StringBuffer();
		for (String key : keys) {
			String value = ini.get(section, key);
			sb.append(key).append(" = ")
			.append(value).append(CRLF);
		}
		
		return sb.toString();

	}

	// 此方法加同步锁
	@Override
	public synchronized void reCreateFilterChains() {
//		ShiroFilterFactoryBean shiroFilterFactoryBean = (ShiroFilterFactoryBean) SpringContextUtil.getBean("shiroFilterFactoryBean");
		AbstractShiroFilter shiroFilter = null;
		try {
			shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean.getObject();
		} catch (Exception e) {
			LoggerUtils.error(getClass(),"getShiroFilter from shiroFilterFactoryBean error!", e);
			throw new RuntimeException("get ShiroFilter from shiroFilterFactoryBean error!");
		}

		PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter
				.getFilterChainResolver();
		DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver
				.getFilterChainManager();

		// 清空老的权限控制
		manager.getFilterChains().clear();

		shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
		shiroFilterFactoryBean.setFilterChainDefinitions(loadFilterChainDefinitions());
		// 重新构建生成
		Map<String, String> chains = shiroFilterFactoryBean
				.getFilterChainDefinitionMap();
		for (Map.Entry<String, String> entry : chains.entrySet()) {
			String url = entry.getKey();
			String chainDefinition = entry.getValue().trim().replace(" ", "");
			manager.createChain(url, chainDefinition);
		}

	}
	public void setShiroFilterFactoryBean(
			ShiroFilterFactoryBean shiroFilterFactoryBean) {
		this.shiroFilterFactoryBean = shiroFilterFactoryBean;
	}

}

具体请查看:

本站发布的开源Demo项目:SpringMVC + Mybatis + Shiro + Redis

Github下载:https://github.com/baichengzhou/SpringMVC-Mybatis-shiro


本文主题

如果本文对你有帮助,那么请你赞助我,让我更有激情的写下去,帮助更多的人。

¥我需要走的更远,点击我 赞助。 如果还有疑问,点击我加群,为你提供最好的解答。


工具导航地图

 
Nodejs + socket Demo 赞助二维码 赞助名单 百度口碑点赞 查看QQ群美女帅哥 点击加QQ群 听音乐 开启弹幕 X
反馈意见