问题描述:
项目使用 SpringMVC 并使用 Shiro 来管理Session控制权限。
经常会不定期的发现异常:
-
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)
-
……………………
通俗的对错误原因描述为:
你所请求的URL是不在Shiro所管辖范围的,而你又在你请求的这个URL后试图通过Shiro来获取Session,所以对Shiro来说“你不让我负责的事,为什么要跟我要结果”。
下面是我web.xml 原来的配置:
-
<filter>
-
<filter-name>shiroFilter
</filter-name>
-
<filter-class>org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
-
<init-param>
-
<param-name>targetFilterLifecycle
</param-name>
-
<param-value>true
</param-value>
-
</init-param>
-
</filter>
-
<filter-mapping>
-
<filter-name>shiroFilter
</filter-name>
-
<url-pattern>/*
</url-pattern>
-
</filter-mapping>
我修改后的配置为:
-
<filter>
-
<filter-name>shiroFilter
</filter-name>
-
<filter-class>org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
-
<init-param>
-
<param-name>targetFilterLifecycle
</param-name>
-
<param-value>true
</param-value>
-
</init-param>
-
</filter>
-
<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>
配置的区别显而易见。
至此,我再说一下,我后来总结出来我出现这个异常的必现操作:就是我访问的页面是404的时候,异常100%出现。
404很明显是一个ERROR,此前我没有添加 <dispatcher>ERROR</dispatcher>,而我在发生错误的时候又使用 SecurityUtils.getSubject().getSession() 来获取Session(我需要从会话中读取相关数据记录日志),所以被Shiro 所拒绝(抛出异常)。
如果你使用Shiro,并且没有配置 <dispatcher>ERROR</dispatcher> 。那么,你登录后,随便访问一个不存在的页面触发404,或者触发500这样的错误页。再回头看登录后的页面,登录状态就丢失了。因为这个时候sessionid 被重新生成覆盖了登录状态时的sessionid。