Spring Boot Shiro在Web应用中的作用详解

 更新时间:2023年02月10日 11:31:03   作者:Samson_bu  
这篇文章主要为大家介绍了Spring Boot Shiro在Web应用中的作用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

01-Tomcat 中的 Filter 责任链

在前面的文章中,我介绍了如何使用 Apache Shiro 进行安全认证。 其实 Shiro 在 Web 应用中出现的频率更高。 今天我将来分析下,Shiro 是如何应用到 Web 应用中的。

Servlet 规范中定义了 Filter 和 FilterChain 接口,其中都包含一个 doFilter 方法,不过参数有区别:

  • Filter#doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  • FilterChain#doFilter(ServletRequest request, ServletResponse response)

Tomcat 中对 FilterChain 的实现是 org.apache.catalina.core.ApplicationFilterChain,它包括:

  • ApplicationFilterConfig[] filters; 数组,用来保存链中的 Filter,ApplicationFilterConfig 是 Filter 的配置类,通过 ApplicationFilterConfig#getFilter() 可获得对应的 Filter。
  • int pos; 表示链当前位置。
  • int n; 表示 FilterChain 中 Filter 的数量,即 filters 中元素数量。
  • Servlet servlet; 表示应用的 Servlet 实现。

ApplicationFilterChain#doFilter 的实现逻辑:

  • 如果 pos < n,即尚未执行到链表末端,则调用 filters[pos++].getFilter().doFilter(req, res, chain),执行当前 Filter 的 doFilter 方法。
  • 如果 pos >= n,说明链表中所有的 Filter 都执行完毕,则调用 servlet.service(request, response);,执行业务层逻辑。

综上,ApplicationFilterChain 会检查是否有 Filter 需要执行,如果有,则调用 Filter;否则,则将请求交给 Servlet 处理。 Filter 在其 doFilter 方法中,能够拿到当前 Filter 所述的 FilterChain 对象。 在执行完 Filter 后,根据自身逻辑判断是否需要继续将请求传递给 chain 上的后续 Filter 处理,若需要,则调用 chain 的 doFilter 方法。

02-Shiro 中的 filter 链结构

Shiro 中对 FilterChain 的实现是 org.apache.shiro.web.servlet.ProxiedFilterChain,它包括:

  • FilterChain orig; 它是 Tomcat 中的 FilterChain 实例。
  • List<Filter> filters; 是 Shiro 中要执行的安全相关的 Filter(它们也都是实现了 Servlet Filter 的类)。
  • int index; 与 ApplicationFilterChain 中的 pos 异曲同工之妙。

ProxiedFilterChain#doFilter 的实现逻辑:

  • 如果 filters == null || index = filters.size() 说明 Shiro 中安全相关的链已执行完毕,则调用 orig.doFilter(req, res)
  • 否则,说明链中当其 Filter 需要执行,则调用 filters.get(index++).doFilter(request, response, this);

03-shiro-filters 如何与 servlet 中的 filter 关联起来

org.apache.shiro.web.servlet.OncePerRequestFilter 实现了 Servlet 中的 Filter 接口,org.apache.shiro.web.servlet.AbstractShiroFilter 是 OncePerRequestFilter 的基本实现。 因此,AbstractShiroFilter 的派生类都能作为 Filter 添加到 Servlet 的责任链中,即 ApplicationFilterChain 的 filters 中。

Shiro 将 AbstractShiroFilter 的一个实现 org.apache.shiro.spring.web.ShiroFilterFactoryBean.SpringShiroFilter 添加到 filters 中,并命名为 "shiroFilter"。 该类的继承关系如下:

注:org.apache.shiro.web.servlet.OncePerRequestFilter 与 Spring 中的 OncePerRequestFilter 同名,但实现不同。

将 shiroFilter 添加到 filters 中的逻辑在 org.apache.shiro.spring.config.web.autoconfigure.ShiroWebFilterConfiguration 中:

@Bean(name = REGISTRATION_BEAN_NAME)
@ConditionalOnMissingBean(name = REGISTRATION_BEAN_NAME)
protected FilterRegistrationBean<AbstractShiroFilter> filterShiroFilterRegistrationBean() throws Exception {

    FilterRegistrationBean<AbstractShiroFilter> filterRegistrationBean = new FilterRegistrationBean<>();
    filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.ERROR);
    filterRegistrationBean.setFilter((AbstractShiroFilter) shiroFilterFactoryBean().getObject());  // SpringShiroFilter 实例
    filterRegistrationBean.setName(FILTER_NAME);    // "shiroFilter"
    filterRegistrationBean.setOrder(1);

    return filterRegistrationBean;
}
复制代码

使用 DEBUG 方式 Shiro Web 应用,也可以佐证上述观点:

Shiro 在 OncePerRequestFilter 中实现了 Filter#doFilter 方法,并在该方法中将过滤器的处理逻辑交由其定义的模板方法 doFilterInternal 来实现。 AbstractShiroFilter 提供了对 doFilterInternal 的基本实现:

将 HttpServletRequest 包装成 ShiroHttpServletRequest

将 HttpServletResponse 包装成 ShiroHttpServletResponse

  • 创建 WebSubject

executeChain(request, response, origChain);,其中 origChain 是 Tomcat 处理请求响应的 ApplicationFilterChain,即 shiroFilter 所在的 chain。

chain = PathMatchingFilterChainResolver#getChain(request, response, origChain); chain 是前面提到的 ProxiedFilterChain 实例。

chain.doFilter(request, response);,相当于将请求交给 shiro-filter 组成的 chain 处理,大体流程与 ApplicationFilterChain 类似。

当请求经过 ApplicationFilterChain 处理,进入到 shiroFilter 时,它的 doFilter 方法(在 OncePerRequestFilter 中)将请求交给 doFilterInternal 方法(在 AbstractShiroFilter 中)处理。 然后会执行与请求路径相关联的 shiro-filter 组成的 chain 对请求、响应进行处理。 下图是 shiro-chain 与 application chain 之间的关系,可以参考下帮助加深理解。

04-总结

今天介绍了 Tomcat 中 Filter 责任链的作用原理以及 Shiro 中实现的安全相关的 Filter 责任链。 并且,还分析了 Shiro 是如何作为一个 Filter 应用到 Web 应用的。 综上,我们了解了一个请求是如何经过层层 Filter 到达 Servlet 中的,也了解了 Shiro 是如何在这个流程中发挥安全认证作用的。 希望以上的内容能对你有所帮助。

以上就是Spring Boot Shiro在Web应用中的作用详解的详细内容,更多关于Spring Boot Shiro Web的资料请关注脚本之家其它相关文章!

相关文章

  • SpringBoot中的自定义Starter解读

    SpringBoot中的自定义Starter解读

    这篇文章主要介绍了SpringBoot中的自定义Starter解读,启动器模块其实是一个空的jar文件,里面没有什么类、接口,仅仅是提供辅助性依赖管理,这些依赖可能用于自动装配或者其他类库,需要的朋友可以参考下
    2023-12-12
  • SpringBoot2 参数管理实践之入参出参与校验的方式

    SpringBoot2 参数管理实践之入参出参与校验的方式

    这篇文章主要介绍了SpringBoot2 参数管理实践,入参出参与校验,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-06-06
  • Spring Boot中@value的常见用法及案例

    Spring Boot中@value的常见用法及案例

    @Value注解是Spring框架中强大且常用的注解之一,本文主要介绍了SpringBoot中@value的常见用法及案例,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • JAVA各种加密与解密方式汇总

    JAVA各种加密与解密方式汇总

    在项目开发中,我们常需要用到加解密算法,本文主要介绍了JAVA各种加密与解密方式汇总,具有一定的参考价值,感兴趣的可以了解一下
    2023-11-11
  • SpringBoot中的@Conditional 注解的使用

    SpringBoot中的@Conditional 注解的使用

    @Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件的才给容器注册Bean,本文主要介绍了SpringBoot中的@Conditional 注解的使用
    2024-01-01
  • 关于Socket的解析以及双方即时通讯的java实现方法

    关于Socket的解析以及双方即时通讯的java实现方法

    本篇文章主要介绍了关于Socket的解析以及双方通讯的java实现方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-03-03
  • kaptcha验证码使用方法详解

    kaptcha验证码使用方法详解

    这篇文章主要为大家详细介绍了kaptcha验证码的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-12-12
  • Dubbo扩展点SPI实践示例解析

    Dubbo扩展点SPI实践示例解析

    这篇文章主要为大家介绍了Dubbo扩展点SPI实践示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • Java中实现List分隔成子List详解

    Java中实现List分隔成子List详解

    大家好,本篇文章主要讲的是Java中实现List分隔成子List详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • java动态方法调度实例分析

    java动态方法调度实例分析

    这篇文章主要介绍了java动态方法调度,结合实例形式对比分析了java的动态方法调度原理、使用方法与注意事项,需要的朋友可以参考下
    2016-06-06

最新评论