Java安全框架——Apache Shiro(三十八)

1,008 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情

【2.4.2】CustomPathMatchingFilterChainResolver
  
package org.apache.shiro.web.filter.mgt;  
  
import javax.servlet.FilterChain;  
import javax.servlet.ServletRequest;  
import javax.servlet.ServletResponse;  
  
  
public interface FilterChainResolver {  
  
    //根据请求获得对应的过滤器链  
    FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain);  
  
}  
  

CustomPathMatchingFilterChainResolver

这里主要核心内容是:指定使用过滤器链管理器为自己定的过滤器管理器

package com.itheima.shiro.core.impl;

import org.apache.shiro.web.filter.mgt.FilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.util.ArrayList;
import java.util.List;

public class CustomPathMatchingFilterChainResolver extends PathMatchingFilterChainResolver {

    private CustomDefaultFilterChainManager customDefaultFilterChainManager;

    public void setCustomDefaultFilterChainManager(CustomDefaultFilterChainManager customDefaultFilterChainManager) {
this.customDefaultFilterChainManager = customDefaultFilterChainManager;
}

    public CustomDefaultFilterChainManager getCustomDefaultFilterChainManager() {
return customDefaultFilterChainManager;
}

    @Override
public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) {
//指定使用过滤器链管理器为自己定的过滤器管理器
FilterChainManager filterChainManager = getCustomDefaultFilterChainManager();
if (!filterChainManager.hasChains()) {
return null;
}

        String requestURI = getPathWithinApplication(request);

        List chainNames = new ArrayList();
//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)) {
return filterChainManager.proxy(originalChain, pathPattern);
}
}
return null;
}
}

【2.4.3】CustomShiroFilterFactoryBean

protected AbstractShiroFilter createInstance() throws Exception {

        log.debug("Creating Shiro Filter instance.");

        SecurityManager securityManager = getSecurityManager();
if (securityManager == null) {
String msg = "SecurityManager property must be set.";
throw new BeanInitializationException(msg);
}

        if (!(securityManager instanceof WebSecurityManager)) {
String msg = "The security manager does not implement the WebSecurityManager interface.";
throw new BeanInitializationException(msg);
}

        FilterChainManager manager = createFilterChainManager();

        //Expose the constructed FilterChainManager by first wrapping it in a
// FilterChainResolver implementation. The AbstractShiroFilter implementations
// do not know about FilterChainManagers - only resolvers:
PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
chainResolver.setFilterChainManager(manager);

        //Now create a concrete ShiroFilter instance and apply the acquired SecurityManager and built
//FilterChainResolver.  It doesn't matter that the instance is an anonymous inner class
//here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts
//injection of the SecurityManager and FilterChainResolver:
return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
}

ShiroFilterFactoryBean源码我们发现PathMatchingFilterChainResolver未暴露set方法,我们改写一下

package com.itheima.shiro.core.impl;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.FilterChainManager;
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.mgt.WebSecurityManager;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.BeanInitializationException;

/**
* @Description:
*/
public class CustomShiroFilterFactoryBean extends ShiroFilterFactoryBean {

    PathMatchingFilterChainResolver chainResolver ;

    public void setChainResolver(PathMatchingFilterChainResolver chainResolver) {
this.chainResolver = chainResolver;
}

    @Override
protected AbstractShiroFilter createInstance() throws Exception {

        SecurityManager securityManager = getSecurityManager();
if (securityManager == null) {
String msg = "SecurityManager property must be set.";
throw new BeanInitializationException(msg);
}

        if (!(securityManager instanceof WebSecurityManager)) {
String msg = "The security manager does not implement the WebSecurityManager interface.";
throw new BeanInitializationException(msg);
}

        FilterChainManager manager = createFilterChainManager();

        chainResolver.setFilterChainManager(manager);

        //Now create a concrete ShiroFilter instance and apply the acquired SecurityManager and built
//FilterChainResolver.  It doesn't matter that the instance is an anonymous inner class
//here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts
//injection of the SecurityManager and FilterChainResolver:
return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
}

    private static final class SpringShiroFilter extends AbstractShiroFilter {

        protected SpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
super();
if (webSecurityManager == null) {
throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
}
setSecurityManager(webSecurityManager);
if (resolver != null) {
setFilterChainResolver(resolver);
}
}
}
}