Shiro 认证权限认证问题

今天使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方法,最后发现了问题,请看下面两张图片:

Shiro 认证权限认证问题_第1张图片

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

Shiro 认证权限认证问题_第2张图片

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

 

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 keys = new LinkedHashSet();

    public Enumeration keys() {
        return Collections.enumeration(keys);
    }

    public Object put(Object key, Object value) {
        keys.add(key);
        return super.put(key, value);
    }

    public Set keySet() {
        return keys;
    }

    public Set stringPropertyNames() {
        Set set = new LinkedHashSet();

        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 getOrderValues(String propertiesFilePath, String encode) {
		Map map = new LinkedHashMap();
		try {
			OrderProperties pros = getOrderProperties(propertiesFilePath, encode);
			Set 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 getOrderValues(String propertiesFilePath) {
		return getOrderValues(propertiesFilePath, null);
	}

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

 

 

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

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

你可能感兴趣的:(Java)