Shiro 认证权限认证问题

来源:互联网 发布:嗒啦咚吧一首网络歌曲 编辑:程序博客网 时间:2024/04/29 18:42

今天使SpringBoot+Shiro做的过程中,遇到一个让自己困惑的问题,首先抛出问题:

/auth/login=anon/person/**=anon/performance/**=anon/**=authc

这些写shiro的配置文件,通过PropertyUtil去获取配置文件,PropertyUtil是通过Properties读取的,按照理想的情况下,我访问/performance/**能够匹配的接口应该是可以访问,但最后发现是不行的,笔者整整纠结了3个多小时......

纠结之后常识将performance改为performances试了一下,太神奇了,竟然可以了,这是为什么呢???(笔者甚至认为performance是Shiro或者Spring的关键字,造成这个问题,真的是这样吗?后面的研究发现笔者错了,太糗了!!!)

笔者下定决心去看看Shiro源码,一层一层调试,找到org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain方法,最后发现了问题,请看下面两张图片:

这张图是performance的图片,请看下面一张performances的图片

仔细分析后,这个地方的顺序不太一样 ,请看下面一段代码:

public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) {        FilterChainManager filterChainManager = getFilterChainManager();        if (!filterChainManager.hasChains()) {            return null;        }        String requestURI = getPathWithinApplication(request);        //the 'chain names' in this implementation are actually path patterns defined by the user.  We just use them        //as the chain name for the FilterChainManager's requirements        for (String pathPattern : filterChainManager.getChainNames()) {            // If the path does match, then pass on to the subclass implementation for specific checks:            if (pathMatches(pathPattern, requestURI)) {                if (log.isTraceEnabled()) {                    log.trace("Matched path pattern [" + pathPattern + "] for requestURI [" + requestURI + "].  " +                            "Utilizing corresponding filter chain...");                }                return filterChainManager.proxy(originalChain, pathPattern);            }        }        return null;    }
通过这个地方可以发现第一张图中的/**可以匹配到/performance/**里面的url,代码执行到这里,符合条件,后面的就不再执行,


研究到这里,发现了问题所在,笔者使用Properties加载属性文件,Properties加载文件后将key、value放入HashMap,这样就造成了Map中的数据根据key的Hash值排序,下面就开始研究解决方案:

1、有序读取Properties文件,下面通过自定义Properties实现,详见代码:

/** * @author Wanxian.He */public class OrderProperties extends Properties {    private static final long serialVersionUID = -4627607243846121965L;    private final LinkedHashSet<Object> keys = new LinkedHashSet<Object>();    public Enumeration<Object> keys() {        return Collections.<Object>enumeration(keys);    }    public Object put(Object key, Object value) {        keys.add(key);        return super.put(key, value);    }    public Set<Object> keySet() {        return keys;    }    public Set<String> stringPropertyNames() {        Set<String> set = new LinkedHashSet<String>();        for (Object key : this.keys) {            set.add((String) key);        }        return set;    }}

有需读取配置文件的工具类:

private static OrderProperties getOrderProperties(String propertiesFilePath, String encode)throws IOException {OrderProperties pros = new OrderProperties();InputStream in = PropertyUtil.class.getResourceAsStream("/" + propertiesFilePath);if (StringUtils.isNotEmpty(encode)) {pros.load(new InputStreamReader(in, encode));} else {pros.load(in);}in.close();return pros;}/** * 获取资源文件里面的key对应的内容 * * @param propertiesFilePath * @param encode * @return */public static Map<String, String> getOrderValues(String propertiesFilePath, String encode) {Map<String, String> map = new LinkedHashMap<String, String>();try {OrderProperties pros = getOrderProperties(propertiesFilePath, encode);Set<String> set = pros.stringPropertyNames();for (String key : set) {String value = pros.getProperty(key);map.put(key, value);}} catch (IOException e) {logger.error("PropertyUtil.getValue(String propertiesFilePath:" + propertiesFilePath+ ") exception ,return null", e);}return map;}/** * 获取资源文件里面的key对应的内容 * * @param propertiesFilePath * @return */public static Map<String, String> getOrderValues(String propertiesFilePath) {return getOrderValues(propertiesFilePath, null);}

2、将有需读取到的Properties文件加载到Shiro的FilterChainDefinitionMap中

Map<String, String> filterMap = PropertyUtil.getOrderValues("ispim_auth.properties");logger.error(filterMap.toString());shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

总结:Shiro进行权限认证的加载是有序的。
截止到目前终于解决这个问题,睡觉。



原创粉丝点击