shiro(1.2.3)在sae平台上不能获取session的问题

两周前准备写个东西练练手,选了sae平台部署我的应用,用了shiro做权限认证,定义只要没登陆就重定向到login页,本地测试登陆没问题,移植到sae就登陆后也跳到了login页,页面输出sessionId=null.cookies中也没有jsessionId,尝试了各种方法,
1.web.xm中添加<distributable />不行,参考http://cloudbbs.org/forum.php?mod=viewthread&tid=5420&page=1#pid32516
2.开启memcache也不行
3.自定义shiro的sessionManager不行,参考 http://cloudbbs.org/forum.php?mod=viewthread&amp ;tid=12905
4.自定义shiro的sessionDao还是不行,参考 http://cloudbbs.org/forum.php?mod=viewthread&amp ;tid=12678

然后各种方法组合,疯了,还是没成功,实际上我就用了一个jvm,不关分布式session的问题。网上发现还是有好些人遇到了同样的问题,但是和shiro相关的帖子都没有成功的解决方法。于是我详细看了段时间shiro的源码,终于让我给发现问题所在,顺利解决,这里贴出来,希望对大家有用。

shiro自己实现了servlet标准,其中org.apache.shiro.web.servlet.ShiroHttpServletRequest继承自javax.servlet.http.HttpServletRequestWrapper,对getSession()等方法做了重写,问题出在这了,shiro的web fileter中有一个org.apache.shiro.web.servlet.AbstractShiroFilter,其他实现filter全部继承自这个类,

 
 protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, final FilterChain chain)
            throws ServletException, IOException {
        Throwable t = null;
        try {
            final ServletRequest request = prepareServletRequest(servletRequest, servletResponse, chain);
            final ServletResponse response = prepareServletResponse(request, servletResponse, chain);
            final Subject subject = createSubject(request, response);
            //noinspection unchecked
            subject.execute(new Callable() {
                public Object call() throws Exception {
                    updateSessionLastAccessTime(request, response);
                 
  executeChain(request, response, chain);
                    return null;
                }
            });
        } catch (ExecutionException ex) {
            t = ex.getCause();
        } catch (Throwable throwable) {
            t = throwable;
        }


        if (t != null) {
            if (t instanceof ServletException) {
                throw (ServletException) t;
            }
            if (t instanceof IOException) {
                throw (IOException) t;
            }
            //otherwise it's not one of the two exceptions expected by the filter method signature - wrap it in one:
            String msg = "Filtered request failed.";
            throw new ServletException(msg, t);
        }
    }
问题就在上面红色部分,shiro用servletRequest创建了ShiroHttpServletRequest实例request,最后又将request传递给过滤链  executeChain(request, response, chain);过滤链调用一个filter传递的已经变成ShiroHttpServletRequest了,最终servlet容器中的request也变成ShiroHttpServletRequest了,sae应该也继承HttpServletRequest对获取session的方法进行了处理比方说缓存,导致了一些不可预料的错误,如session.getId()==null;稍微修改这个类方法,就好了:

protected void doFilterInternal(final ServletRequest servletRequest,final ServletResponse servletResponse, final FilterChain chain)
            throws ServletException, IOException {
        Throwable t = null;
        try {
            final ServletRequest request = prepareServletRequest(servletRequest, servletResponse, chain);
            final ServletResponse response = prepareServletResponse(request, servletResponse, chain);
            final Subject subject = createSubject(request, response);
            //noinspection unchecked
            subject.execute(new Callable() {
                public Object call() throws Exception {
                    updateSessionLastAccessTime(request, response);
                   
executeChain(servletRequest, servletResponse, chain);
                    return null;
                }
            });
        } catch (ExecutionException ex) {
            t = ex.getCause();
        } catch (Throwable throwable) {
            t = throwable;
        }
        if (t != null) {
            if (t instanceof ServletException) {
                throw (ServletException) t;
            }
            if (t instanceof IOException) {
                throw (IOException) t;
            }
            //otherwise it's not one of the two exceptions expected by the filter method signature - wrap it in one:
            String msg = "Filtered request failed.";
            throw new ServletException(msg, t);
        }
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值