开发者社区 问答 正文

Shiro在Spring MVC中使用DeferredResult出错

一个项目使用了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>



然后就返回500了,有些数据还是会在返回500前把数据正常返回到前端。web.xml中也启用了<async-supported>true</async-supported>。不知道有没有人遇到这个问题。

展开
收起
huc_逆天 2020-05-28 09:22:23 974 分享 版权
阿里云 AI 助理回答

遇到这个问题,通常是因为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异步支持的集成方式,确保两者兼容且配置正确。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答