Spring Boot Shiro auto-configure工作流程详解

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

01-Shiro 自动配置原理

Shiro 与 Spring Boot 集成可以通过 shiro-spring-boot-stater 实现,并能完成必要类自动装配。 实现方式是通过 Spring Boot 的自动配置机制,即 WEB-INF/spring.factories 中通过 EnableAutoConfiguration 指定了 6 个自动化配置类:

org.springframework.boot.autoconfigure.EnableAutoConfiguration = \
  org.apache.shiro.spring.config.web.autoconfigure.ShiroWebAutoConfiguration,\
  org.apache.shiro.spring.config.web.autoconfigure.ShiroWebFilterConfiguration,\
  org.apache.shiro.spring.config.web.autoconfigure.ShiroWebMvcAutoConfiguration,\
  org.apache.shiro.spring.boot.autoconfigure.ShiroBeanAutoConfiguration,\
  org.apache.shiro.spring.boot.autoconfigure.ShiroAutoConfiguration,\
  org.apache.shiro.spring.boot.autoconfigure.ShiroAnnotationProcessorAutoConfiguration

它们之间的关系为:

当配置项 shiro.enabled = trueshiro.web.enabled = false 时,ShiroWeb*Configuration 配置不生效。 当 shiro.web.enabled = true 时,上述六个皆生效,不过 ShiroWebAutoConfiguration 上有注解 @AutoConfigureBefore(ShiroAutoConfiguration.class), 保证能在 ShiroAutoConfiguration 之前,使用 web 配置覆盖 standalone 配置

02-自动配置类

Shiro 中的核心是 SecurityManager,它将 Authenticator、Authorizer、SessionManager 等关键模块组合在一起。 在 ShiroWebAutoConfiguration 中包含了上述几个核心模块的默认初始化过程。

对 Authenticator 来说(ShiroWebAutoConfiguration 返回的都是父类方法的内容,所以下面我直接将方法体替换为父类的):

@Bean
@ConditionalOnMissingBean
@Override
protected AuthenticationStrategy authenticationStrategy() {
    return new AtLeastOneSuccessfulStrategy();
}
@Bean
@ConditionalOnMissingBean
@Override
protected Authenticator authenticator() {
    ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
    authenticator.setAuthenticationStrategy(authenticationStrategy());
    return authenticator;
}

默认情况下,使用的是 ModularRealmAuthenticator,策略类使用的事 AtLeastOneSuccessfulStrategy,即多个 Realms 时,至少一个成功则认为是成功。

对 Authorizer 来说:

@Bean
@ConditionalOnMissingBean
@Override
protected Authorizer authorizer() {
    ModularRealmAuthorizer authorizer = new ModularRealmAuthorizer();
    if (permissionResolver != null) {
        // 负责从 permission 字符串里解析出 Permission 对象
        authorizer.setPermissionResolver(permissionResolver);  // 这两个都是通过 @Autowired 注入进来的
    }
    if (rolePermissionResolver != null) {
        // 负责从 role 字符串里解析出 Permission 集合
        authorizer.setRolePermissionResolver(rolePermissionResolver);  // 这两个都是通过 @Autowired 注入进来的
    }
    return authorizer;
}

对于 SessionManager 来说:

@Bean
@ConditionalOnMissingBean
@Override
protected SessionManager sessionManager() {
    if (useNativeSessionManager) {  // 从环境变量 shiro.userNativeSessionManager 取,默认为 false
        // 省略了其他设置
        return new DefaultWebSessionManager();
    }
    return new ServletContainerSessionManager();
}

对于 SecurityManager 来说:

@Bean
@ConditionalOnMissingBean
@Override
protected SessionsSecurityManager securityManager(List<Realm> realms) {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setSubjectDAO(subjectDAO());
    securityManager.setSubjectFactory(subjectFactory());
    securityManager.setRememberMeManager(rememberMeManager());
    securityManager.setAuthenticator(authenticator());
    securityManager.setAuthorizer(authorizer());
    securityManager.setRealms(realms);
    securityManager.setSessionManager(sessionManager());
    securityManager.setEventBus(eventBus);
    if (cacheManager != null) {
    securityManager.setCacheManager(cacheManager);
    }
    return securityManager;
}

对于其他对象,例如 SubjectDAO/SubjectFactory、SessionDAO/SessionFactory/SessionManager、RememberMeManager、EventBus,在系统中属于比较底层的辅助模块,一般与业务牵扯比较小,所以通过情况下不需要修改。 我简单介绍下它们的作用,以及 Shiro Web 应用中使用得默认类型:

  • SubjectFactory 有两个默认实现,DefaultSubjectFactory 和 DefaultWebSubjectFactory 分别用来创建 standalone 和 Web 程序中的 Subject 对象。
  • SubjectDAO 有一个默认实现,DefaultSubjectDAO 负责将 Subject 对象存储到其所属的 Session 对象中。
  • RememberMeManager 负责将 Subject 的 principals 存储到 cookie 中。
  • EventBus 是 Shiro 中的事件总线,负责在 Shiro 全声明周期触发特定事件或接受事件通知。
  • SessionDAO/SessionFactory/SessionManager 是与 Session 管理、持久化相关的模块。

03-Filter 相关的配置类

ShiroWebFilterConfiguration 中定义了与 Servlet Filter 相关的对象。 对于 ShiroFilterFactoryBean,负责创建 shiroFilter 对象:

@Bean
@ConditionalOnMissingBean
@Override
protected ShiroFilterFactoryBean shiroFilterFactoryBean() {
    ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
    // 从环境变量中取
    filterFactoryBean.setLoginUrl(loginUrl);   // shiro.loginUrl
    filterFactoryBean.setSuccessUrl(successUrl); // shiro.successUrl
    filterFactoryBean.setUnauthorizedUrl(unauthorizedUrl); // shiro.unauthorizedUrl
    filterFactoryBean.setSecurityManager(securityManager);  // 由 @Autowired 注入
    filterFactoryBean.setShiroFilterConfiguration(shiroFilterConfiguration()); // 由 @Autowired 注入或默认使用 ShiroFilterConfiguration
    filterFactoryBean.setGlobalFilters(globalFilters()); // 由 @Autowired 注入
    filterFactoryBean.setFilterChainDefinitionMap(shiroFilterChainDefinition.getFilterChainMap()); // 由 @Autowired 注入
    filterFactoryBean.setFilters(filterMap); // 由 @Autowired 注入
    return filterFactoryBean;
}

对于 filterShiroFilterRegistrationBean 来说,负责向 ServletContext 中注册 shiroFilter 对象:

@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());  // 有前面的 FactoryBean 创建
    filterRegistrationBean.setName(FILTER_NAME);  // shiroFilter
    filterRegistrationBean.setOrder(1);
    return filterRegistrationBean;
}

关于 globalFilters,默认只有 InvalidRequestFilter:

@Bean(name = "globalFilters")
@ConditionalOnMissingBean
protected List<String> globalFilters() {
    return Collections.singletonList(DefaultFilter.invalidRequest.name());
}

通过前面的分析,如果业务需要针对不同的 URL 使用不同的 shiro-filter chain,可以通过自定义 shiroFilterChainDefinition 并将其注入都容器中即可,例如:

@Bean
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
    DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
    chainDefinition.addPathDefinition("/manage/index", "user");
    chainDefinition.addPathDefinition("/manage/logout", "logout");
    chainDefinition.addPathDefinition("/manage/**", "authc");
    // shiro 放行 swagger
    chainDefinition.addPathDefinition("/swagger-ui/**", "user");
    chainDefinition.addPathDefinition("/swagger-resources/**", "user");
    chainDefinition.addPathDefinition( "/v3/api-docs/**","user");
    chainDefinition.addPathDefinition("/**", "anon");
    return chainDefinition;
}

04-总结

今天,我介绍了 shiro-spring-boot-starter 中对 Shiro 进行自动化配置的细节。 通过对这些配置的了解,能够在遇到具体的业务问题时修改特定模块的实现方式,对理解和使用 Shiro 框架是非常必要的事情。 希望今天的内容能对你有所帮助,更多关于Spring Boot Shiro auto-configure的资料请关注脚本之家其它相关文章!

相关文章

  • 详细全面解析Java泛型

    详细全面解析Java泛型

    这篇文章主要介绍了详细全面解析Java泛型,java泛型主要提高了Java 程序的类型安全,通过知道使用泛型定义的变量的类型限制,编译器可以验证类型假设,消除源代码中的许多强制类型转换等多个有点,下面我们进入文章了解更多的详细内容吧
    2022-02-02
  • Java分页简介_动力节点Java学院整理

    Java分页简介_动力节点Java学院整理

    这篇文章主要为大家详细介绍了Java分页简介的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • springboot实现定时任务的四种方式小结

    springboot实现定时任务的四种方式小结

    本文主要介绍了springboot实现定时任务的四种方式小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • Hadoop上Data Locality的详解

    Hadoop上Data Locality的详解

    这篇文章主要介绍了 Hadoop上Data Locality的详解的相关资料,希望通过本文能帮助到大家,让大家理解掌握这部分内容,需要的朋友可以参考下
    2017-10-10
  • java中struts2实现文件上传下载功能实例解析

    java中struts2实现文件上传下载功能实例解析

    这篇文章主要介绍了java中struts2实现文件上传下载功能的方法,以实例形式较为详细的分析了struts2实现文件上传下载功能的具体实现技巧与相关问题的解决方法,具有一定的参考借鉴价值,需要的朋友可以参考下
    2015-01-01
  • Java中垃圾回收器GC对吞吐量的影响测试

    Java中垃圾回收器GC对吞吐量的影响测试

    这篇文章主要介绍了Java中垃圾回收器GC对吞吐量的影响测试,本文算是一个对垃圾回收器GC的优化文章,需要的朋友可以参考下
    2014-09-09
  • IDEA2023.3.4开启SpringBoot项目的热部署(图文)

    IDEA2023.3.4开启SpringBoot项目的热部署(图文)

    本文使用的开发工具是idea,使用的是springboot框架开发的项目,配置热部署,可以提高开发效率,文中通过图文介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2024-02-02
  • Spring Cloud oauth2 认证服务搭建过程示例

    Spring Cloud oauth2 认证服务搭建过程示例

    这篇文章主要为大家介绍了Spring Cloud oauth2 认证服务搭建过程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • java实现周期性执行(定时任务)

    java实现周期性执行(定时任务)

    这篇文章主要为大家详细介绍了java实现周期性执行定时任务,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-09-09
  • 浅谈如何在项目中使用Spring Cloud Alibaba Sentinel组件

    浅谈如何在项目中使用Spring Cloud Alibaba Sentinel组件

    随着微服务的流行,服务和服务之间的稳定性变得越来越重要。本文主要介绍了使用Spring Cloud Alibaba Sentinel组件,感兴趣的可以了解一下
    2021-07-07

最新评论