ajax302请求重定向解决跳转失败,包括shiro session会话重定向问题

概要

  • 背景
    在开发过程中完成session共享时测试session中断过期页面响应而遇到了问题。

  • 技术使用
    springboot+redis+shiro+静态html分离式前端

解决办法

首先要弄懂一个问题,为什么服务端写了重定向,前端页面没有去跳转?并且重定向里的请求location也指向清楚了。
因为ajax请求里涉及返回两种类型,一种是返回json,一种是返回页面内容,如果纯粹的返回内容的话就走304,页面去读缓存了,然后重定向在阻塞,导致页面没有刷新,当手工刷新才加载304要显示的页面内容。


手动再现一下之前的场景,下图为综合过程结果:
综合过程

  • ajax请求,发送/findList查询到后台服务端
$.ajax({
    url:serverUrl+'/departments/findList',
    type:'post',
    data: row,
    async:false,
    success: function (data) {
        if (data.success) {
            $.messager.alert("错误");
        }
    }
});
  • 接着服务端拦截器处理请求,博主使用的shiro管理会话和权限,所以会拦截请求做对应的的校验,若校验失败(本例以session失效演示),则进入filter设置好的重定向目录/sessionFailure
    shiro过滤器设置

  • 由于session失效或权限不足等情况引起的框架(或用户自己使用redirect之类的跳转)重定向,会直接在ServletResponse里设置head的location值,告诉前端请求,向这个新地址重新请求,那么之前请求的/findList,压根就没有到具体业务运行的代码上就已经去执行新的请求了/sessionFailure,如最开始的第一张过程图

  • 之后我们在请求/sessionFailure中做对应业务处理,有2种返回方式:页面返回和json返回。从现在的开发来看,如果使用的页面返回,那么是适用于伪前后端分离和不分离的项目架构,这里只需要使用脚本语言即可,会自动帮你处理好response的页面展示;

  • 从前后端分离式开发看,服务端是不做页面返回的,所以统一以json返回,前端自行处理返回的状态,根据状态自行处理静态页面的跳转,但现在前端大多都采用框架结构了,并且前端语言和库更加丰富,实际上前端也在做mvc、mvv开发,具体使用什么语言博主不做说明(因为只会vue2),博主做这个文章是建立在纯静态html+jquery的前端上实现的,也就是说会用ajax+jquery做到全局处理的事情
/**
     * 会话过期 -- 用户处于未登录状态
     * @param response
     */
    @RequestMapping("/sessionFailure")
    public ModelAndView sessionFailure(HttpSession session, HttpServletResponse response) {
        System.out.println(SecurityUtils.getSubject().getSession().getAttribute(SessionStatus.STATUS));
        if (null == getCurrentUser()) {
            response.setHeader(SessionStatus.STATUS, SessionStatus.EXPIRED);
        }
        //方法1:返回页面内容跳转
        ModelAndView model = new ModelAndView();
        model.addObject("result", Result.result(1, false, StatusCode.LOGINOUT, ResultType.LOGINOUT));
        //model.setViewName("forward:/user/login.html");
        model.setViewName("redirect:/user/login.html");

        //方法2:ajax-json返回,由前端捕获自行操作代码
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("sessionStatus", "expired");
        result.put("message", ResultType.LOGINOUT);
        result.put("code", StatusCode.LOGINOUT);

        //方法2包装
        doResult(response, flag, StatusCode.DEFAULT, null, flag ? "通过" : "失败");
        return model;
    }
  • 如果你使用的是跟博主类似的环境,并且是前后端分离式开发,那么建议使用上述的方法2,自己包装返回json,不要返回页面。创建一个js,加入如下引用,在index页面引入一下
$.ajaxSetup({ 
    asycn: false,
    xhrFields: {
        withCredentials: true
    },
    error: function (XMLHttpRequest, textStatus, errorThrown){
        if(XMLHttpRequest.status==403){
            alert('您没有权限访问此资源或进行此操作');
            return false;
        }
    }, 
    contentType:"application/x-www-form-urlencoded;charset=utf-8",
    complete: function (XMLHttpRequest,textStatus) {
        debugger;
        //通过XMLHttpRequest取得响应头,sessionstatus
        var sessionstatus = XMLHttpRequest.getResponseHeader("sessionStatus"); 
        //通过XMLHttpRequest取得返回的json
        var json = XMLHttpRequest.responseJSON;
        //通过XMLHttpRequest取得返回的text
        var text = XMLHttpRequest.responseText;
    }
}); 
  • 不懂ajaxSetup可以看一下,ajaxSetup是一个类似前端ajax父级的东西,也就是说如果有了这个,你的页面里写的其他$.ajax就是它的子集,会默认带上ajaxSetup上设置的属性,另外ajaxSetup的一些方法如dataFilter、complete、success都是
    在你的ajax请求时会去执行的方法(至于先执行还是后执行,不是本文讨论的方法,后续做详细介绍)。

  • 这里博主是利用的complete监听所有的ajax请求,在请求执行完成后进入方法,执行后续动作,若服务端在重定向执行我上述的/sessionFailure请求时返回了json,那么就使用XMLHttpRequest.responseText去读取服务端返回的json内容,判断你返回的状态,上面代码服务端的例子是用的sessionStatus,所以现在前端例子上也是用这个办法,博主列举了可行的三种方式,任选。

总结

有问题留言交流,博主比较懒,草稿箱里有四十多篇没写完的博客,只能趁现在工作不忙,一段时间一篇慢慢还原环境去补充了,累!!!!

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在使用 Spring Boot 和 Shiro 框架的时候,如果用户长时间不进行操作,会话就会超时。可以通过以下方式来解决会话超时的问题: 1. 设置会话超时时间 可以通过在 shiro.ini 或者 shiro.yml 配置文件中设置超时时间,例如: ``` sessionManager.globalSessionTimeout = 1800000 ``` 这里设置了会话超时时间为 1800000 毫秒,即 30 分钟。 2. 使用 keep-alive 机制 可以在前端页面使用 keep-alive 机制,保持与后端的连接,防止会话超时。例如,在 Vue.js 中可以使用 keep-alive 组件: ``` <keep-alive> <router-view></router-view> </keep-alive> ``` 3. 在会话超时时进行跳转 可以在 Shiro 的配置文件中设置会话超时时的跳转页面,例如: ``` sessionManager.globalSessionTimeout = 1800000 securityManager.sessionManager = $sessionManager securityManager.sessionManager.sessionIdUrlRewritingEnabled = false securityManager.sessionManager.sessionValidationSchedulerEnabled = true securityManager.sessionManager.sessionValidationInterval = 1800000 securityManager.sessionManager.deleteInvalidSessions = true securityManager.sessionManager.sessionIdCookieEnabled = true securityManager.sessionManager.sessionIdCookie.name = JSESSIONID securityManager.sessionManager.sessionIdCookie.path = / securityManager.sessionManager.sessionIdCookie.httpOnly = true securityManager.sessionManager.sessionIdCookie.maxAge = -1 securityManager.sessionManager.sessionIdCookie.domain = securityManager.sessionManager.sessionIdCookie.sameSite = null securityManager.sessionManager.sessionValidationScheduler.interval = 1800000 shiro.filter.loginUrl = /login shiro.filter.successUrl = /index shiro.filter.unauthorizedUrl = /unauthorized securityManager.realms = $jdbcRealm ``` 在配置文件中设置 unauthorizedUrl 属性,用于在会话超时时进行跳转。 以上是解决 Spring Boot 和 Shiro 框架会话超时问题的几种方法,希望能够帮到你。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值