博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ShiroFilterFactoryBean分析
阅读量:6877 次
发布时间:2019-06-26

本文共 6186 字,大约阅读时间需要 20 分钟。

创建核心Filter

同其他框架一样,都有个切入点,这个核心Filter就是拦截所有请求的。

通过web.xml中配置的Filer进入,执行init方法获取这个instance,调用下面的createInstance方法创建核心Filter:

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);}

createFilterChainManager方法比较重要,包含以下必要操作:

  1. DefaultFilterChainManager对象的创建

  2. defaultFilters的获取和相关url的填充

  3. 自定义filters的获取和相关url的填充

  4. 获取FilterChainDefinitionMap (这个就是配置文件中的filterChainDefinitions的映射关系)

  5. 对url和权限的映射关系作处理

默认的DefaultFilter枚举中包含以下filter类:

anon(AnonymousFilter.class),authc(FormAuthenticationFilter.class),authcBasic(BasicHttpAuthenticationFilter.class),logout(LogoutFilter.class),noSessionCreation(NoSessionCreationFilter.class),perms(PermissionsAuthorizationFilter.class),port(PortFilter.class),rest(HttpMethodPermissionFilter.class),roles(RolesAuthorizationFilter.class),ssl(SslFilter.class),user(UserFilter.class);

执行doFilter方法

看下内部类 SpringShiroFilter:

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); } }}

这里写图片描述

在org.apache.shiro.web.servlet.OncePerRequestFilter中实现了doFilter方法:

public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)        throws ServletException, IOException {    String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();    if ( request.getAttribute(alreadyFilteredAttributeName) != null ) {        log.trace("Filter '{}' already executed.  Proceeding without invoking this filter.", getName());        filterChain.doFilter(request, response);    } else //noinspection deprecation        if (/* added in 1.2: */ !isEnabled(request, response) ||            /* retain backwards compatibility: */ shouldNotFilter(request) ) {        log.debug("Filter '{}' is not enabled for the current request.  Proceeding without invoking this filter.",                getName());        filterChain.doFilter(request, response);    } else {        // Do invoke this filter...        log.trace("Filter '{}' not yet executed.  Executing now.", getName());        request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);        try {            doFilterInternal(request, response, filterChain);        } finally {            // Once the request has finished, we're done and we don't            // need to mark as 'already filtered' any more.            request.removeAttribute(alreadyFilteredAttributeName);        }    }}

三种情况,分为两条路线:

1. filterChain.doFilter(request, response); 直接放行
2. doFilterInternal(request, response, filterChain); 走子类实现

在org.apache.shiro.web.servlet.AbstractShiroFilter实现doFilterInternal:

protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, final FilterChain chain)        throws ServletException, IOException {    Throwable t = null;    try {        final ServletRequest request = prepareServletRequest(servletRequest, servletResponse, chain);        final ServletResponse response = prepareServletResponse(request, servletResponse, chain);        final Subject subject = createSubject(request, response);        //noinspection unchecked        subject.execute(new Callable() {            public Object call() throws Exception {                updateSessionLastAccessTime(request, response);                executeChain(request, response, chain);                return null;            }        });    } catch (ExecutionException ex) {        t = ex.getCause();    } catch (Throwable throwable) {        t = throwable;    }    if (t != null) {        if (t instanceof ServletException) {            throw (ServletException) t;        }        if (t instanceof IOException) {            throw (IOException) t;        }        //otherwise it's not one of the two exceptions expected by the filter method signature - wrap it in one:        String msg = "Filtered request failed.";        throw new ServletException(msg, t);    }}

将HttpServletRequest和HttpServletResponse包装成shiro自己的ShiroHttpServletRequest和ShiroHttpServletResponse。

利用包装后的对象创建Subject。

然后是执行subject的execute的方法。

protected void executeChain(ServletRequest request, ServletResponse response, FilterChain origChain)        throws IOException, ServletException {    FilterChain chain = getExecutionChain(request, response, origChain);    chain.doFilter(request, response);}

获取的FilterChain是一个代理的ProxiedFilterChain,持有自己的Filter集合,重写doFilter方法:取自己持有的Filter集合,一个个执行其doFilter方法,当所有的Filter都执行完后,再执行servlet的FilterChain。

后面的过程就是一个原始的FilterChain的执行过程。

可以想象,原生的Filter链似乎也是这样一个执行过程,遍历web.xml中配置的所有Filter。

整个过程就是代理模式的运用。

这里写图片描述

转载于:https://www.cnblogs.com/lucare/p/8679136.html

你可能感兴趣的文章
PAT (Advanced Level) 1107. Social Clusters (30)
查看>>
POJ 3494 Largest Submatrix of All 1’s
查看>>
Ubuntu系统分配存储空间的建议以及给Ubuntu系统根目录扩容方法(从20GB追加100GB)...
查看>>
centos 查询mysql配置文件位置
查看>>
Eclipse IDE 使用技巧(一)
查看>>
用Word写博客园文章
查看>>
sh cssupdate
查看>>
如何让多出的文本用省略号表示
查看>>
【转】CentOS 7 安装配置 NFS
查看>>
WebLog Expert
查看>>
TFT LCD显示原理详解
查看>>
类型库 type library
查看>>
python之virtualenv
查看>>
sql效率
查看>>
Python绘图和数值工具:matplotlib 和 numpy下载与使用
查看>>
php - 从数据库导出百万级数据(CSV文件)
查看>>
安卓开发自定义View的框架学习
查看>>
spark-groupByKey
查看>>
redis 随笔
查看>>
LOJ#2302 整数
查看>>