web集成shiro(1)

Q1:shiro过滤器是如何添加到servlet的过滤器链?和servlet原生拦截器是如何配合工作的?shiro是如何filter是如何拦截请求的?
Q3:shiro是如何实现账号密码验证的?
Q4:shiro是如何实现角色权限认证的?


A1:
ShiroFilterFactoryBean的getObject方法(实现spring的FactoryBean工厂方法),会创建一个SpringShiroFilter的Bean:
protected AbstractShiroFilter createInstance() throws Exception {
    FilterChainManager manager = this.createFilterChainManager();
    PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
    // 设置了FilterChainManager和PathMatchingFilterChainResolver ,它将根据请求url,决定是否执行shrio代理链
    chainResolver.setFilterChainManager(manager);
    return new ShiroFilterFactoryBean.SpringShiroFilter((WebSecurityManager)securityManager, chainResolver);
}

SpringShiroFilter 是实现了Filter接口的,所以由spring自动加载到ServeltContext中,自然就加入了执行器链

几个主要类的父子关系:SpringShiroFilter -> AbstractFilter -> OncePerRequestFilter

父类:OncePerRequestFilter

Filter顶层接口doFilter的实现方法为这个方法,会加入到servlet的执行器链:

public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) {
        。。。。。。
                this.doFilterInternal(request, response, filterChain);
        。。。。。。

    }
doFilterInternal是一个抽象方法,由子类AbstractFilter实现:

protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, final FilterChain chain)  {
       。。。           
       this.executeChain(request, response, chain);
       。。。
}

protected void executeChain(ServletRequest request, ServletResponse response, FilterChain origChain)  {
        // 获取执行器链,由执行器链执行doFilter

        FilterChain chain = this.getExecutionChain(request, response, origChain);
        chain.doFilter(request, response);
}

那么这个resolver拿到的chain到底是一个什么chain???

protected FilterChain getExecutionChain(ServletRequest request, ServletResponse response, FilterChain origChain) {
        FilterChain chain = origChain;
        FilterChainResolver resolver = this.getFilterChainResolver();
        。。。
        FilterChain resolved = resolver.getChain(request, response, origChain);
        。。。
        return chain;
}

resolver实际是一个PathMatchingFilterChainResolver对象

PathMatchingFilterChainResolver类

// 主要检查当前请求的url是否匹配shiro filter的拦截路径,如果是,则返回ProxiedFilterChain
public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) {
        FilterChainManager filterChainManager = this.getFilterChainManager();
        。。。。。。
        return filterChainManager.proxy(originalChain, pathPattern);
}

 

DefaultFilterChainManager类

// 对象属性,已经实例化好了,filter不会反复创建,浪费资源;
// 打上断点发现:filterChains的key是url,value是filterList;如下图所示:
web集成shiro(1)_第1张图片
实际上一个url是可以配置多个filter的

Map filterChains = new LinkedHashMap();

// 当登陆login的时候,断点发现:chainName = /login
public FilterChain proxy(FilterChain original, String chainName) {
       // getChain从filterChains属性中获取的NamedFilterList
        NamedFilterList configured = this.getChain(chainName);
        if (configured == null) {
            String msg = "There is no configured chain under the name/key [" + chainName + "].";
            throw new IllegalArgumentException(msg);
        } else {
            return configured.proxy(original);
        }
}

SimpleNamedFilterList类(NamedFilterList实现类)

public FilterChain proxy(FilterChain orig) {
  // this指向就是shiro的Filters,实际上在DefaultFilterChainManager属性中已经实例化好了orig是外部传入的原生执行器链,
  // 所以需要new只是ProxiedFilterChain代理对象
   return new ProxiedFilterChain(orig, this);
}

ProxiedFilterChain类(这就是常说shrio代理链)
public class ProxiedFilterChain implements FilterChain {
  
    // 代理的原生的severlet处理器链
    private FilterChain orig;
    // shiro的filter链
    private List filters;
    private int index = 0;

    public ProxiedFilterChain(FilterChain orig, List filters) {
            this.orig = orig;
            this.filters = filters;
            this.index = 0;
    }

   //  实现了FilterChain接口,适配标准的servlet处理器链

   public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
        if (this.filters != null && this.filters.size() != this.index) {

            ((Filter)this.filters.get(this.index++)).doFilter(request, response, this);
        } else {
            // shiro的filter全部执行完成后,执行完成原生的处理器链

            this.orig.doFilter(request, response);
        }

    }
}

 

你可能感兴趣的:(java)