自定义shiro过滤器没有Set Cookie问题。

本文详细介绍了在使用Shiro自定义过滤器处理Ajax请求时遇到的SetCookie问题,即非登录用户在响应时缺少SetCookie,导致sessionId不断变化,前端无法获取JSESSIONID。通过对比Shiro的源码,发现在返回false之前缺少了saveRequest(request)操作,补充这一操作后解决了问题。此问题的关键在于理解Shiro的Session管理和过滤器流程。
摘要由CSDN通过智能技术生成

自定义shiro过滤器没有Set Cookie问题。

比如我们通常会针对ajax的请求,返回json数据,一般的实现大概是这样。

public class MyUserFilter extends UserFilter {

    @Override
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String requestedWith = request.getHeader("X-Requested-With");
        Subject subject = SecurityUtils.getSubject();
        if (!subject.isRemembered() && !subject.isAuthenticated() && StringUtils.isNotEmpty(requestedWith)
                && StringUtils.equals(requestedWith, "XMLHttpRequest")) {//如果是ajax返回指定数据
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            response.getWriter().write(JSONObject.toJSONString(ResultBean.noLogin("请先登录")));
            return false;
        } else {//不是ajax进行重定向处理
            return super.onAccessDenied(request, response);
        }

    }
    
}

这个基本满足了ajax请求的拦截后返回json的需求,但是引起了一个非常怪的问题,非登录用户,网站在响应的时候没有Set Cookie的动作(清理缓存后,这个问题百分百重现),也就是在后台会产生这样一个问题:每次非登录用户的sessionId一直在变,前端的请求没有相应的JSESSIONID(自定义的名称)。

先上解决方法,在return false之前执行saveRequest(request),即:

if (!subject.isRemembered() && !subject.isAuthenticated() && StringUtils.isNotEmpty(requestedWith)
    && StringUtils.equals(requestedWith, "XMLHttpRequest")) {//如果是ajax返回指定数据
  // 省略,同上
  super.saveRequest(request);
  return false;
} else {//不是ajax进行重定向处理
  return super.onAccessDenied(request, response);
}
解决过程:

我反复找原因,反复对比,发现问题就是出在自定义的过滤器这里。

网上找了一大圈,竟然都没有相关的回答,我只能去参考shiro的UserFilter,查看了AccessControlFilter中的

protected void saveRequestAndRedirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
  saveRequest(request);
  redirectToLogin(request, response);
}

发现它是有一个saveRequest操作,代码如下:

public static void saveRequest(ServletRequest request) {
  Subject subject = SecurityUtils.getSubject();
  Session session = subject.getSession();
  HttpServletRequest httpRequest = toHttp(request);
  SavedRequest savedRequest = new SavedRequest(httpRequest);
  session.setAttribute(SAVED_REQUEST_KEY, savedRequest);
}

可以明显地看到,它是有个session key的设置动作的。

像在我自己实现的onAccessDenied中,return false前没有保存动作,那么JSESSIONID就不会保存,然后这个JSESSIONID大概会在哪里被清空,并且不会再response,那么之后在登录之前,前端都不会有这个id,

所以在return false之前加上saveRequest(request),可以解决前端没有JSESSIONID的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值