最近刚接到手的jwt+shiro的项目整合,发现一直有个问题,token错误后,他会一直在JWTFilter中不断循环,最终报:
java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
如上错误
正因为形成了死循环,导致了response多次的请求,报了这个错误,初步断定,是Filter中有问题,异常没抛出来,进入到JWTFilter中,断点发现确实如此.
try {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
//设置编码,否则中文字符在重定向时会变为空字符串
httpServletResponse.sendRedirect("/user/401");
} catch (IOException e) {
System.out.println(e.getMessage());
很明显,在token失效后,我设置了重定向到/user/401这个接口中的代码没有执行到我想要的目的.可能是ShiroConfig中配置了拦截所有资源导致的,
打开发现
// 所有的请求通过我们自己的JWT filter
filterRuleMap.put("/**", "jwt");
// 访问401和404页面不通过我们的Filter,一定只能先放行资源,在拦截资源
filterRuleMap.put("/user/401", "anon");
filterRuleMap.put("/user/404", "anon");
果然放行代码是写了,但是因为按照shiro官方的说法,放行的资源要放在拦截的资源前,因此我作出如下修改
// 访问401和404页面不通过我们的Filter,一定只能先放行资源,在拦截资源
filterRuleMap.put("/user/401", "anon");
filterRuleMap.put("/user/404", "anon");
// 所有的请求通过我们自己的JWT filter
filterRuleMap.put("/**", "jwt");
再次运行,成功通过,也可重定向到错误信息接口.
这个死循环就因为Token无效后,会随着重定向,携带token过去,因为拦截下来,被JWT继续检测到了token,继续拦截,重复解密,然后token继续失效,无限循环,知道里面抛出异常.