一直要学习 2020-08-17 16:50 采纳率: 100%
浏览 1299
已采纳

定时任务里调用SecurityUtils.getSubject()方法报错

ssm项目+shiro
配置了定时任务如下:

<bean name="Job" class="bpp.controller.Job"/>
    <bean id="job" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <!-- 执行的类 -->
        <property name="targetObject">
            <ref bean="Job"/>
        </property>
        <!-- 类中的方法 -->
        <property name="targetMethod">
            <value>getData</value>
        </property>
    </bean>

想要在定时任务里获取当前登录信息,所以:
User user=(User) SecurityUtils.getSubject().getPrincipal();
但是报错:

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:626)
    at org.apache.shiro.SecurityUtils.getSubject(SecurityUtils.java:56)

不知道为啥,其他controller都能用,排除网上说的filter没配好,就是定时任务没法获取,听说是Thread的问题,不知道为啥,有没有大佬知道。。。错在哪,怎么获取登录信息啊。。。多谢多谢

debug到源码,就是获取不到securityManager

 SecurityManager securityManager = ThreadContext.getSecurityManager();
        if (securityManager == null) {
            securityManager = SecurityUtils.securityManager;
        }
        if (securityManager == null) {
            String msg = "No SecurityManager accessible to the calling code, either bound to the " +
                    ThreadContext.class.getName() + " or as a vm static singleton.  This is an invalid application " +
                    "configuration.";
            throw new UnavailableSecurityManagerException(msg);
        }

就是ThreadContext.getSercurity为null,再往下走:

 public static SecurityManager getSecurityManager() {
        return (SecurityManager) get(SECURITY_MANAGER_KEY);
    }

虽然是打了断点,但是好像断点对定时任务没用,看不到具体的空值:

public static Object get(Object key) {
        if (log.isTraceEnabled()) {
            String msg = "get() - in thread [" + Thread.currentThread().getName() + "]";
            log.trace(msg);
        }

        Object value = getValue(key);
        if ((value != null) && log.isTraceEnabled()) {
            String msg = "Retrieved value of type [" + value.getClass().getName() + "] for key [" +
                    key + "] " + "bound to thread [" + Thread.currentThread().getName() + "]";
            log.trace(msg);
        }
        return value;
    }

当前线程不可能获取不到,所以就是当前线程找不到指定的key但是,为啥,是因为定时任务给自己新开了一个独立的线程,而这个线程和用户登录的那个线程无关吗。。。唉,心累

  • 写回答

4条回答 默认 最新

  • 怀人 2020-08-18 16:56
    关注

    先说,我不知道定时中怎么获取,但我认为你的方法有问题。
    1.定时任务是跑在服务端的任务调度,和有没有用户登录、用户登不登陆完全没关系
    2.SecurityUtils获取用户信息的使用,肯定要在一次网络请求的上下文中,不然连用户这个概念都找不到
    我觉得这个设计逻辑不正确,应该要换一下吧

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 matlab实现基于主成分变换的图像融合。
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制
  • ¥20 usb设备兼容性问题
  • ¥15 错误(10048): “调用exui内部功能”库命令的参数“参数4”不能接受空数据。怎么解决啊