一个项目使用了spring mvc的DeferredResult异步,其它都正常,当使用这个异步方法时会触发
org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContext or as a vm static singleton. This is an invalid application configuration.
查询一些方案也无效,比如
<filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>ERROR</dispatcher> </filter-mapping>
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
遇到这个问题,通常是因为Apache Shiro的SecurityManager在异步执行的线程中不可用。Spring MVC的DeferredResult
允许你在不同的线程中处理请求并随后完成响应,而Shiro默认是基于当前线程(通常是HTTP请求处理线程)上下文来管理安全信息的。当你的逻辑切换到另一个线程时,Shiro的SecurityManager实例没有被正确地传递过去。
解决这个问题的一个常见方法是在异步任务开始之前手动绑定SecurityManager到新线程的上下文中。Shiro提供了org.apache.shiro.util.ThreadContext
类来帮助你实现这一点。你需要在执行异步操作前,将当前的SecurityManager设置到新线程中。以下是一个示例代码片段:
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ThreadContext;
// 在调用异步方法之前
Subject currentUser = SecurityUtils.getSubject();
ThreadContext.bind(currentUser);
deferredResult.onCompletion(() -> {
// 清理线程上下文,防止内存泄漏
ThreadContext.unbindSubject();
});
这段代码首先获取当前的Subject(这会自动包含对SecurityManager的引用),然后将其绑定到ThreadContext
中。这样,在新的异步线程里就可以访问到Shiro的SecurityManager了。同时,使用onCompletion
回调来确保在异步处理完成后解除绑定,以避免潜在的内存泄漏问题。
请根据你的具体应用环境调整上述代码,并确保在所有可能触发异步执行的路径上都进行了这样的处理。如果问题依然存在,可能需要进一步检查Shiro的配置以及与Spring MVC异步支持的集成方式,确保两者兼容且配置正确。