一、前言
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. 是比较常见的Shiro报错,一般出现在获取当前用户信息(即:
SecurityUtils.getSubject()
)的时候,没有找到SecurityManager。这种报错可能是正常的 也可以能是异常的。本文将就这两种情况进行说明
二、定时任务中报错
这种属于正常报错,定时任务属于服务端运行任务,并没有明确的用户指向,当前用户是不明确的,无法获取也是属于正常情况。**比较简单的处理方案是增加 try ..catch
**将异常捕获即可。或者缺啥咱给补上就完事了,如下代码:
// 在调用SecurityUtils.getSubject()之前setSecurityManager()设置一下
public void setSecurityManager() {
// 获取当前线程的SecurityManager
SecurityManager securityManager = ThreadContext.getSecurityManager();
if (securityManager == null) {
// 获取注入到Spring的SecurityManager,将其设置到当前线程
SecurityUtils.setSecurityManager(applicationContext.getBean(SecurityManager.class));
}
}
三、异步线程中报错
这种属于异常报错,如果你是在异步线程(通常在线程池中出现)中获取当前用户报上述错误,你可以采用如下方案:
注意:此处线程池使用的是Spring内置的ThreadPoolTaskExecutor bean
@Configuration
public class ThreadPoolTaskExecutorConfig {
public ThreadPoolTaskExecutorConfig(@Qualifier("applicationTaskExecutor") ObjectProvider<ThreadPoolTaskExecutor> taskExecutorObjectProvider) {
taskExecutorObjectProvider.ifAvailable(taskExecutor -> taskExecutor.setTaskDecorator(runnable -> {
try {
// shiro 向下传递当前线程的用户信息
return SecurityUtils.getSubject().associateWith(runnable);
} catch (UnavailableSecurityManagerException e) {
// 用户信息不存在,直接执行
return runnable;
}
}));
}
}