前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >shiro之深度解析FormAuthenticationFilter

shiro之深度解析FormAuthenticationFilter

作者头像
用户4919348
发布2019-05-14 09:43:35
1.5K0
发布2019-05-14 09:43:35
举报
文章被收录于专栏:波波烤鸭波波烤鸭

  shiro是我们在项目经常使用到的权限管理框架,本文我们就重点来分析FormAuthenticationFilter的验证过程。

FormAuthenticationFilter

1.继承结构

  我们首先来看下FormAuthenticationFilter的继承结构,这样更加便于我们去分析

在这里插入图片描述
在这里插入图片描述

2.父类的作用

  从上面的继承结构图里我们发现FormAuthenticationFilter的继承结构还是蛮负责的,我们先一个个来介绍下他们的作用。然后具体分析

作用

AbstractFilter

加载FilterConfig的相关信息

NameableFilter

定义每一个filter的名字

OncePerRequestFilter

保证客户端请求后该filter的doFilter只会执行一次

AdviceFilter

主要是对doFilterInternal做了更细致的处理

PathMatchingFilter

主要是对preHandle做进一步细化控制

AccessControlFilter

对onPreHandle方法做了进一步细化

AuthenticationFilterAuthenticatingFilter

用来做认证的Filter

FormAuthenticationFiltershiro

用来具体的实现登录的Filter

3.具体分析

  接下具体看下每个Filter中主要的方法的作用及实现。

3.1 NameableFilter

  NameableFilter有一个name属性,定义每一个filter的名字.在FilterChainManager 中会调用配置文件中的配置属性名字来为每一个filter命名以及为默认的filter命名,如authc.

在这里插入图片描述
在这里插入图片描述

3.2 OncePerRequestFilter

  OncePerRequestFilter保证客户端请求后该filter的doFilter只会执行一次.当满足拦截条件的请求到来的时候执行的就是本方法中的OncePerRequestFilter 中的doFilter方法:

代码语言:javascript
复制
    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);
            }
        }
    }

  doFilter的实质内容是在doFilterInternal方法中完成的。所以实质上是保证每一个filter的 doFilterInternal只会被执行一次,例如在配置中配置路径 /user/** = authc,authc.则只会执行authc中的doFilterInternal一次。doFilterInternal非常重要,在shiro整个filter体系中的核心方法及实质入口。另外,shiro是通过在request中设置一个该filter特定的属性值来保证该filter只会执行一次的。   enabled属性决定了是否执行本Filter。

enabled状态

说明

true

表示是否启用这个filter,默认是true

false

跳过这个filter的doFilterInternal方法而去执行filter链中其他filter

3.3 AdviceFilter

  在OncePerRequestFilter中调用的doFilterInternal方法是个抽象方法,具体的实现是在AdviceFilter中,而且AdviceFilter对于doFilterInternal方法做了更细致的处理。如下:

在这里插入图片描述
在这里插入图片描述

  此处的处理和SpringMVC中的interceptor很类似。

方法

说明

preHandle

前置的判断处理,如果返回false则filter链不继续往下执行

postHandle

在目标方法(即客户端请求的接口)正常(未抛出异常)执行后完成一些操作,默认不做任何操作

cleanup

会调用afterCompletion方法,不管目标方法是否出现异常都会继续操作。默认也是空

  AdviceFilter总体是对OncePerRequestFilter中的doFilterInternal进一步细化控制

3.4 PathMatchingFilter

  PathMatchingFilter主要是对preHandle做进一步细化控制,该filter为抽象类,其他路径直接通过:preHandle中,若请求的路径非该filter中配置的拦截路径,则直接返回true进行下一个filter。若包含在此filter路径中,则会在isFilterChainContinued做一些控制,该方法中会调用onPreHandle方法,所以子类可以在onPreHandle中编写filter控制流程代码(返回true或false)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.5 AccessControlFilter

  onPreHandle方法在PathMatchingFilter就简单的返回了true,在AccessControlFilter 中更细化的实现了。

代码语言:javascript
复制
   public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) 
   throws Exception {
       return isAccessAllowed(request, response, mappedValue) 
       || onAccessDenied(request, response, mappedValue);
   }

  isAccessAllowed方法和onAccessDenied方法达到控制效果。这两个方法都是抽象方法,由子类去实现。到这一层应该明白。isAccessAllowed和onAccessDenied方法会影响到onPreHandle方法,而onPreHandle方法会影响到preHandle方法,而preHandle方法会达到控制filter链是否执行下去的效果。所以如果正在执行的filter中isAccessAllowed和onAccessDenied都返回false,则整个filter控制链都将结束,不会到达目标方法(客户端请求的接口),而是直接跳转到某个页面(由filter定义的,将会在authc中看到)

3.6 AuthenticatingFilter

  AuthenticationFilter和AuthenticatingFilter认证的filter,在抽象类中AuthenticatingFilter实现了isAccessAllowed方法,该方法是用来判断用户是否已登录,若未登录再判断是否请求的是登录地址,是登录地址则放行,否则返回false终止filter链。

代码语言:javascript
复制
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
    Subject subject = getSubject(request, response);
    return subject.isAuthenticated();
}
代码语言:javascript
复制
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
    return super.isAccessAllowed(request, response, mappedValue)
     ||(!isLoginRequest(request, response) 
     && isPermissive(mappedValue));
}

  提供了executeLogin方法实现用户登录的,还定义了onLoginSuccess和onLoginFailure方法,在登录成功或者失败时做一些操作。登录将在下面详细说明

在这里插入图片描述
在这里插入图片描述

3.7 FormAuthenticationFiltershiro

  FormAuthenticationFiltershiro提供的登录的filter,如果用户未登录,即AuthenticatingFilter中的isAccessAllowed判断了用户未登录,则会调用onAccessDenied方法做用户登录操作。若用户请求的不是登录地址,则跳转到登录地址,并且返回false直接终止filter链。若用户请求的是登录地址,若果是post请求则进行登录操作,由AuthenticatingFilter中提供的executeLogin方法执行。否则直接通过继续执行filter链,并最终跳转到登录页面(因为用户请求的就是登录地址,若不是登录地址也会重定向到登录地址)

在这里插入图片描述
在这里插入图片描述

  在来看executeLogin方法,

在这里插入图片描述
在这里插入图片描述

onLoginSuccess

在这里插入图片描述
在这里插入图片描述

onLoginFailure

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  若登录成功返回false(FormAuthenticationFiltershiro的onLoginSuccess默认false),则表示终止filter链,直接重定向到成功页面,甚至不到达目标方法直接返回了。若登录失败,直接返回true(onLoginFailure返回false),继续执行filter链并最终跳转到登录页面,该方法还会设置一些登录失败提示 shiroLoginFailure,在目标方法中可以根据这个错误提示制定客户端更加友好的错误提示。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年04月30日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • FormAuthenticationFilter
    • 1.继承结构
      • 2.父类的作用
        • 3.具体分析
          • 3.1 NameableFilter
          • 3.2 OncePerRequestFilter
          • 3.3 AdviceFilter
          • 3.4 PathMatchingFilter
          • 3.5 AccessControlFilter
          • 3.6 AuthenticatingFilter
          • 3.7 FormAuthenticationFiltershiro
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档