错误描述
在shiro实现权限控制下集成quartz2;集成成功后发现定时任务在执行是报如下错误:
2018-01-24 15:35:23 [ scheduler_Worker-1:2076922 ] - [ ERROR ] Job (job_2480F7EA027E461C9ED2E06B8555FF8D.job_7D928929B8694450B39FE67740159FDC threw an exception.
org.quartz.SchedulerException: Job threw an unhandled exception. [See nested exception: 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.]
at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: 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.
at org.apache.shiro.SecurityUtils.getSecurityManager(SecurityUtils.java:123)
at org.apache.shiro.subject.Subject$Builder.<init>(Subject.java:627)
at org.apache.shiro.SecurityUtils.getSubject(SecurityUtils.java:56)
解决方法
然后查询资料发现shiro实现是针对quartz1.6版本的实现(详细源码请查看QuartzSessionValidationScheduler),在quartz2.2.1中,SimppleTrigger为接口,所以无法实例化;网上好多方法都是进行重写,参考:http://www.hillfly.com/2017/178.html
由于定时任务模块已经成形不想修改太多,后面查看报错源头在org.apache.shiro.SecurityUtils:
没有找到securityManager实例对象,在源码里可以发现获取securityManager调用了ThreadContext中的方法,在追踪ThreadContext源码发现其实就是用map来存储securityManager对象。securityManager对象为shiro为安全管理器通过在配置文件中通过spring注入
然后利用spring特性就做出来大胆的尝试:在定时任务执行时在execute方法中直接实例化了securityManager在利用ThreadContext方法存入securityManager对象;
这样就不会报错了,但是不是知道这样实例securityManager的方法对框架什么影响还有待探究
2018/1/26 问题补充
最后发现以上修改方式,当程序运行一段时间后报出了一下错误
org.apache.shiro.session.UnknownSessionException: There is no session with id [bae5ddd9-1745-4667-98d2-bb10c10f7623]
at org.apache.shiro.session.mgt.eis.AbstractSessionDAO.readSession(AbstractSessionDAO.java:170)
at com.eims.modules.rbac.security.session.SessionDao.doReadSession(SessionDao.java:34)
问题最后追踪发现 在每次执行完定时任务后回去更新定时任务自定义任务信息,用到了更新UpdateUser;在获取UpdateUser是用到了org.apache.shiro.session.Session
/**
*
* @Title: getSession
* @Description: TODO 获取当前的ession,R如果为空创建一个新的Session
* @return Session 返回类型
* @throws
*/
public static Session getSession(){
try{
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession(false);
if (session == null){
session = subject.getSession();
}
if (session != null){
return session;
}
}catch (InvalidSessionException e){
}
return null;
}
最终解决方案:
去掉了之前的securityManager的添加;最后修改UpdateUser设置为固定值,不用session就没有出现过错误了