You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Grails 2升级至5后部署Tomcat9出现Shiro SecurityManager异常

Grails5升级后Tomcat9部署Shiro异常排查方案

问题根因

Tomcat9的类加载机制和Grails嵌入式Tomcat存在差异,导致Shiro的SecurityManager在容器启动阶段还未完成初始化就被调用,虽然应用功能能正常运行,但初始化过程中会抛出org.apache.shiro.UnavailableSecurityManagerException。核心矛盾是容器环境下Spring上下文的加载顺序和嵌入式Tomcat不同,部分组件提前触发了SecurityManager的获取操作。

修复步骤

1. 确认Shiro插件版本适配

Grails5和Java11对Shiro插件版本有明确要求,别沿用Grails2时期的旧插件。打开项目的build.gradle,检查Shiro依赖版本,建议使用适配Grails5的4.x系列稳定版:

implementation "org.grails.plugins:shiro:4.0.0" // 版本以实际兼容情况为准,可参考Grails官方插件库

2. 延迟SecurityManager初始化

在grails-app/conf/spring/resources.groovy中手动声明SecurityManager Bean,并设置延迟初始化,避免容器启动时就强制加载:

import org.apache.shiro.web.mgt.DefaultWebSecurityManager

beans = {
    securityManager(DefaultWebSecurityManager) {
        realms = ref('yourCustomRealm') // 替换为项目中实际的Realm Bean名称
        lazyInit = true
    }
}

这样SecurityManager会在第一次被实际调用时才完成初始化,避开容器启动的早期阶段。

3. 排查Tomcat类加载隔离问题

FreeBSD上的Tomcat可能存在类加载隔离配置,导致Shiro核心类被容器类加载器和应用类加载器重复加载,引发SecurityManager实例无法共享:

  • 检查Tomcat的conf/catalina.properties文件,查看shared.loader配置项是否包含Shiro相关Jar包,如有则删除该配置,确保所有Shiro依赖都存在于应用的WEB-INF/lib目录中。

4. 修正SecurityManager获取逻辑

如果代码中直接使用SecurityUtils.getSecurityManager()静态方法,改成从Spring上下文获取实例,避免因调用时机过早导致的异常:

import org.apache.shiro.mgt.SecurityManager;
import org.springframework.web.context.support.WebApplicationContextUtils;

// 在Web请求上下文内获取SecurityManager
SecurityManager securityManager = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext())
        .getBean(SecurityManager.class);
SecurityUtils.setSecurityManager(securityManager);

5. 对比依赖树排查冲突

分别查看嵌入式Tomcat和外部Tomcat部署时的依赖差异,找出潜在冲突:

  • 执行./gradlew dependencies生成完整依赖树,检查是否有旧版本Shiro被间接引入。
  • 用./gradlew dependencyInsight --dependency org.apache.shiro:shiro-core命令定位具体依赖来源,排除冲突版本。

内容的提问来源于stack exchange,提问作者susi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 05:05:48