Junit+Spring MockMvc+Shiro时出现SessionContext和SecurityManager的错误解决方式

来源:互联网 发布:p2p理财跑路汇总数据 编辑:程序博客网 时间:2024/06/06 04:32

目录

  • 目录
  • JunitSpring MockMvcShiro时出现SessionContext和SecurityManager的错误解决方式
    • 第一个错误
    • 第二个错误
    • 解决方法

Junit+Spring MockMvc+Shiro时出现SessionContext和SecurityManager的错误解决方式

使用Junit测试SpringMvc,用spring-test MockMvc的时候,由于系统里配置了shiro。
导致一些奇怪的错误。

第一个错误

org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContextor as a vm static singleton. This is an invalid application configuration.

这个错误我用了这个方法来解决:

    @Before    public void setShiro() {        SecurityUtils.setSecurityManager(context.getBean(SecurityManager.class));    }

这个解决方法互联网上很多人都说了。

然后又出现了第二个错误。

第二个错误

java.lang.IllegalArgumentException: SessionContext must be an HTTP compatible implementation.    at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.createSession(ServletContainerSessionManager.java:103)    at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.start(ServletContainerSessionManager.java:64)    at org.apache.shiro.mgt.SessionsSecurityManager.start(SessionsSecurityManager.java:121)    at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:336)    at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:314)

然后这个错误是遍查网上都没有啊。于是我开始调试源码(这是我经常的手段)

PS:my version : shiro-1.2.0
首先定位到错误堆栈信息最上层,因为Exception就是从这里抛出的。
有很多经验不足的开发者,碰到异常总不知所措。最好的方法就是追根溯源,看它哪里报错。

 protected Session createSession(SessionContext sessionContext) throws AuthorizationException {        if (!WebUtils.isHttp(sessionContext)) {            String msg = "SessionContext must be an HTTP compatible implementation.";            throw new IllegalArgumentException(msg);        } else {            HttpServletRequest request = WebUtils.getHttpRequest(sessionContext);            HttpSession httpSession = request.getSession();            String host = this.getHost(sessionContext);            return this.createSession(httpSession, host);        }    }

看到是一个判断条件为false了。我现在是debug模式,F5跟进去,发现里面还有一个重载。

 private static boolean isHttp(RequestPairSource source) {        ServletRequest request = source.getServletRequest();        ServletResponse response = source.getServletResponse();        return request instanceof HttpServletRequest && response instanceof HttpServletResponse;    }

最后我发现request和response是null。null instanceof anything always return false。
知道原因之后,我就开始往上层代码找

最后找到是Shiro里面的SubjectContext里面的setServletRequestsetServletResponse方法根本没有调用,导致为null。

由于我的项目正常启动不报错,就是junit报错,于是我在这两个方法中下了断点(这几个类maven好像没有源码,只是class,idea反编译的,不能查找。)

然后我正常启动项目,在堆栈里发现是AbstractShiroFIlter调用的,有了这个线索,解决方式就水落石出了。原来是ShiroFIlter在junit,mockmvc环境中没有被加入。

解决方法

最后解决方式是:

DefaultMockMvcBuilder<DefaultMockMvcBuilder<?>> builder = MockMvcBuilders.webAppContextSetup(context);//这一句builder.addFilters((Filter) context.getBean("shiroFilter"));

然后我尝试把第一个错误的解决代码去掉,发现也能正常运行。
……。

就到这里吧,我本来就不是喜欢写博客的人,突然想记录一下自己的解决问题的过程,分享给大家,希望大家喜欢。
过去工作中,好多类似的奇葩问题,我都没有记录博客,现在想起来也有点遗憾。不过都记在我心里了,如果以后再碰到,我条件反射就会解决了,那时候再记下来吧。

原创粉丝点击