最近公司开发一个微信小程序项目加shiro的项目。因为微信小程序是不使用cookie,使用的是 storage 。那么我们就不能使用传统的方式来保持登录状态了。
1.首先和网上的一样,先重写一个Session管理器
public class MySessionManager extends DefaultWebSessionManager { private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request"; @Override protected Serializable getSessionId(ServletRequest request, ServletResponse response) { System.out.println("执行session管理器>>>>>>>>>>>>>>>>>>>>>>>>"); String id = WebUtils.toHttp(request).getHeader("TOKEN"); if(StringUtils.isEmpty(id)){ //如果没有携带id参数则按照父类的方式在cookie进行获取 return super.getSessionId(request, response); }else{ //如果请求头中有 token 则其值为sessionId request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,REFERENCED_SESSION_ID_SOURCE); request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID,id); request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID,Boolean.TRUE); return id; } } }
2.将自定义的session管理器交给spring管理
@Configuration public class ShiroConfig { @Bean public DefaultWebSecurityManager securityManager(){ DefaultWebSecurityManager manager = new DefaultWebSecurityManager(); manager.setRealm(realm()); manager.setSessionManager(defaultWebSessionManager()); return manager; } @Bean public DefaultWebSessionManager defaultWebSessionManager(){ MySessionManager manager = new MySessionManager(); return manager; } ...... }
到这里看样子似乎是没有什么事情了,但是事与愿违,因为我登陆成功之后,每次都被登录过滤器给拦截了。这是为啥嘞?
经过几轮的debug调试才发现,原来在调用完之后 getSessionId方法之后会有一个设置过期时间的过程(当然这个很正常),默认给设置的是1800,刚开始我觉得没什么毛病啊。就没理他,可是继续往下debug的时候发现报错信息竟然是回话已超时,之后就被登录过滤器给定义为登录失败了(囧)。话说不是已经设置了默认的过期时间了吗? 然后我不服,重写了设置过期时间的方法
@Override public void setTimeout(SessionKey key, long maxIdleTimeInMillis) throws InvalidSessionException { super.setTimeout(key, 3600000); }
结果就好了。一定要仔细看第二个参数 maxIdleTimeInMillis 这是最大过期时间的毫秒值啊!!!默认给个1800,不就是1.8秒吗?那这样的话想要让这个回话不过期只能自己设置一个比较大的过期时间了,或者你可以做这时间上最快的男人每1.8秒内就请求一次,这样shiro就会重置过期时间。