Shiro源码分析系列:02.Filters的执行流程

默认Filter

name class effect
anon AnonymousFilter 都可以访问
authc FormAuthenticationFilter 登录之后才能进行访问,不包括remember me
user UserFilter 登录用户才可以访问,包含remember me
logout LogoutFilter 立即登出登陆
......

自定义Filter

不同的登陆处理逻辑需要继承不同类型的FIlter,比如,依赖web表单登陆的业务需要继承FormAuthenticationFilter,未登录的接口都会重定向到LoginUrl。自己处理登陆逻辑(比如token)的接口应该继承PassThruAuthenticationFilter,登陆失败可以返回错误码。不过所有的Filter只是认证结果不一致,整个认证的逻辑都是一致的。
Shiro的Filter统一交给ShiroFilterFactoryBean处理,配置文件看起来像这样:

 
        
        
            
                
                    
                        
                        
                    
                
                
                    
                        
                        
                        
                        
                        
                        
                        
                    
                
                
            
        
        
            
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
            
        
    

Filter执行流程

下面的分析流程我们以Post提交表单登陆为例(FormAuthenticationFilter)。
通过第一篇,我们已经知道shrio是如何从Spring MVC中接管web请求的,并且循环调用配置的filters,接下来先看一张filter执行的概览图:


2.0.Filter执行流程.jpg
  1. 调用FormAuthenticationFilter.doFilter()方法,判断当前filter有没有重复执行;
  2. 调用doFilterInternal(),真正执行fiter认证流程,执行剩余的filter的链条,请求交给mvc的其他的filter;
  3. 调用preHandle方法,返回值非常重要,决定当前的请求要不要继续走剩余的流程。

接下来,详细分析preHandle方法的执行流程:
1.先判断当前请求能否被处理


image.png
  1. 调用onPreHandle()方法
isAccessAllowed(request, response, mappedValue) || onAccessDenied(request, response, mappedValue);

2.1 isAccessAllowed()本质是从线程局部变量获取Subject对象,判断是否授权。如果是fasle,就会判断是否不是登陆请求&&filter忽略(返回true)。因为登陆请求交给下一步处理
如果返回true,则表示当前请求已经登陆或不是登陆请求且是该Filter忽略的,直接放行。
2.2 当第一步返回false时候,就会调用onAccessDenied()方法,处理未认证的逻辑。


image.png

先判断是否为登陆请求,再判断是否是登陆提交表单。是登陆提交表单,就之心executeLogin方法,否则就放行这个filter,跳转登陆页面。
过不是登陆请求,重定向到登陆页面,返回false,filter结束本次请求。

  1. executeLogin()执行登陆请求方法


    image.png

    3.1 从登录表单请求中获取用户名和密码,封装为Token,自定义Token可以重写createToken()
    3.2 获取Shiro的上文对象
    3.3 把包含登陆信息的token执行登陆请求,具体调用Realm的登陆方法,上下文对象中就会存储已经成功认证的信息,下次请求在2.1处就会直接放行。接下来会具体分析Realm的登陆流程。
    3.4 登陆成功回调的方法


    image.png

    至此,认证的闭环流程完成,3.4的重定向的请求到达2.1的isAccessAllowed()就会返回true,filter直接放行这个请求。
    接下的章节会详细分析登陆的subject.login()方法和Subject对象如何让存储登陆信息。

你可能感兴趣的:(Shiro源码分析系列:02.Filters的执行流程)