Shiro中session超时页面跳转的处理方式

目录
  • session超时页面跳转的处理
    • 问题描述
    • ajax请求超时处理
    • 非ajax请求超时跳转
  • 一个判断session是否过期的小技巧
    • 1.session其实就是一个Map
    • 2.session的过期时间是从什么时候开始计算的?
    • 3.设置session的失效时间
    • 4.如何判断session过没过期

session超时页面跳转的处理

问题描述

shiro在管理session后,在session超时会进行跳转,这里有两种情况需要考虑,一种是ajax方式的请求超时,一种页面跳转请求的超时。

本文从这两个方面分别考虑并处理。

ajax请求超时处理

思路:通过Filter后判定,当前是否session超时,超时判定是否是ajax请求,如果是ajax请求,则在response头部设置session-status值,返回到前端读取到相应值后进行处理

后端Filter代码

package com.cnpc.framework.filter;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * * filter过滤器,获取项目路径,设置ajax超时标识
 * @author billJiang QQ:475572229
 */
public class SystemFilter implements Filter {
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException,
            ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        System.out.println(request.getRequestURL());
        String basePath = request.getContextPath();
        request.setAttribute("basePath", basePath);
        if (!SecurityUtils.getSubject().isAuthenticated()) {
            //判断session里是否有用户信息
            if (request.getHeader("x-requested-with") != null
                    && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
                //如果是ajax请求响应头会有,x-requested-with
                response.setHeader("session-status", "timeout");//在响应头设置session状态
                return;
            }
        }
        filterChain.doFilter(request, servletResponse);
    }
    @Override
    public void destroy() {
        // TODO Auto-generated method stub
    }
    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub
    }
}

前端通用ajax处理

注意session-status上下文部分

function ajaxPost(url, params, callback) {
    var result = null;
    var headers={};
    headers['CSRFToken']=$("#csrftoken").val();
    $.ajax({
        type : 'post',
        async : false,
        url : url,
        data : params,
        dataType : 'json',
        headers:headers,
        success : function(data, status) {
            result = data;
            if(data&&data.code&&data.code=='101'){
                modals.error("操作失败,请刷新重试,具体错误:"+data.message);
                return false;
            }
            if (callback) {
                callback.call(this, data, status);
            }
        },
        error : function(err, err1, err2) {
            console.log("ajaxPost发生异常,请仔细检查请求url是否正确,如下面错误信息中出现success,则表示csrftoken更新,请忽略");
            console.log(err.responseText);
            if(err && err.readyState && err.readyState == '4'){
                var sessionstatus=err.getResponseHeader("session-status");
                if(sessionstatus=="timeout"){
                    //如果超时就处理 ,指定要跳转的页面
                    window.location.href=basePath+"/" ;
                }
                else{//csrf异常
                    var responseBody = err.responseText;
                    if (responseBody) {
                        responseBody = "{'retData':" + responseBody;
                        var resJson = eval('(' + responseBody + ')');
                        $("#csrftoken").val(resJson.csrf.CSRFToken);
                        this.success(resJson.retData, 200);
                    }
                    return;
                }
            }
            modals.error({
                text : JSON.stringify(err) + '
err1:' + JSON.stringify(err1) + '
err2:' + JSON.stringify(err2),
                large : true
            });
        }
    });
    return result;
}

非ajax请求超时跳转

在本试验中,使用jquery.load方式进行了页面加载,并重载jquery.fn.load改写了该方法,通过beforeSend去除了ajax标识,由于超时返回的登录页面可能嵌入当前页面,所以需要判断当前获得的页面是否是登录页面,如果是登陆页面,则再经过一次跳转到登陆页(或者首页)。

重载的jquery.fn.load方法如下,注意beforeSend和responseText.startWith部分内容。

var _old_load = jQuery.fn.load;
jQuery.fn.load = function( url, params, callback ) {
    //update for HANZO, 2016/12/22
    if (typeof url !== "string" && _old_load) {
        return _old_load.apply( this, arguments );
    }
    var selector, type, response,
        self = this,
        off = url.indexOf( " " );
    if ( off > -1 ) {
        selector = jQuery.trim( url.slice( off ) );
        url = url.slice( 0, off );
    }
    if ( jQuery.isFunction( params ) ) {
        callback = params;
        params = undefined;
    } else if ( params && typeof params === "object" ) {
        type = "POST";
    }
    if ( self.length > 0 ) {
        jQuery.ajax( {
            url: url,
            beforeSend: function( xhr ) {
                    xhr.setRequestHeader('X-Requested-With', {toString: function(){ return ''; }});
            },
            type: type || "GET",
            dataType: "html",
            data: params
        } ).done( function( responseText ) {
            //console.log(responseText);
            response = arguments;
            //页面超时跳转到首页
            if(responseText.startWith("<!--login_page_identity-->")){
                window.location.href=basePath+"/";
            }else{
                self.html(selector ?
                    jQuery("<div>").append(jQuery.parseHTML( responseText )).find(selector) :
                    responseText);
            }
        } ).always( callback && function( jqXHR, status ) {
            self.each( function() {
                callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
            } );
        } );
    }
    return this;
};

可通过设置session的timeout来测试结果。需要注意的是ajax请求要使用ajaxPost方法,该方法统一处理了超时跳转。

一个判断session是否过期的小技巧

Session一直是我们做web项目经常使用的,以前没太注意,这次又细致的看了下!

1.session其实就是一个Map

键=值对,通过session.getAttribute("name");获得session中设置的参数

2.session的过期时间是从什么时候开始计算的?

是从一登录就开始计算还是说从停止活动开始计算?

答:从session不活动的时候开始计算,如果session一直活动,session就总不会过期。

从该Session未被访问,开始计时; 一旦Session被访问,计时清0;

3.设置session的失效时间

a)web.xml中

<session-config>    
    <session-timeout>30</session-timeout>    
</session-config>   

b)在程序中手动设置

session.setMaxInactiveInterval(30 * 60);//设置单位为秒,设置为-1永不过期

c)tomcat也可以修改session过期时间,在server.xml中定义context时采用如下定义:

<Context path="/livsorder" docBase="/home/httpd/html/livsorder"  
  defaultSessionTimeOut="3600" isWARExpanded="true"  
  isWARValidated="false" isInvokerEnabled="true"  
  isWorkDirPersistent="false"/>  

4.如何判断session过没过期

request.getSeesion(boolean)方法,一下子让我恍然大悟。这个方法里面传了一个boolean值,这个值如果是true,那么如果当前的request的session不可用,那么就创建新的会话,如果存在就返回当前的会话。如果参数是false,那么在request的当前会话不存在的时候就返回null。

这样我们就可以很容易的联想到这个所谓的request的当前会话是否存在和session过期的联系,所以我们就可以“近似地”认为session不存在就是session过期了,那么我们就可以很容易地判断session是否过期了。

方法如下:

if(request.getSession(false)==null)
   System.out.println("Session has been invalidated!");
else
   System.out.println("Session is active!");

可能大家注意到我上面有一个“近似地”字眼,也就是说存在特别情况。

这个特殊情况就是第一次请求还没有创建会话的时候,那么用这个方法返回的仍然是null,原因我想大家应该是显然的。

private boolean checkSession(    HttpServletRequest request,
HttpServletResponse response) {
HttpSession session = request.getSession(false);
String requestURI = request.getRequestURI();
String contextPath = request.getContextPath();
 
requestURI = requestURI.substring(contextPath.length());
 
if(requestURI.equals("/") ||
requestURI.equals("/login.jsp") ||
     requestURI.equals("/login.do")    ||
     requestURI.equals(this.errorPage))
return true;
 
if(session != null 
&& session.getAttribute(this.objName) != null 
&& session.getAttribute("year") != null)
return true;
else 
return false;
}

比较好的一个办法

//request.getSession(false)==null可以近似的判断是否过期:如果已经过期,那么返回的是null,但是当起一次请求,刚刚建立一个session的时候,上述方法也返回null 
//所以应该这个做 
if(null==request.getSession(false)){ 
   if(true==request.getSession(true).isNew()){ 
      } 
else{ 
System.out.println("session已经过期"); 
} 
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Session过期后自动跳转到登录页面的实例代码

    最近做了一个项目其中有需求,要实现自动登录功能,通过查阅相关资料,打算用session监听来做,下面给大家列出了配置监听器的方法: 1.在项目的web.xml文件中添加如下代码: <!--添加Session监听器--> <listener> <listener-class> 监听器路径 </listener-class> </listener> 2.编写java类. public class SessionListener implements

  • 解决Shiro 处理ajax请求拦截登录超时的问题

    目录 Shiro 处理ajax请求拦截登录超时 配置全局ajax配置 Shiro session超时页面跳转的处理 问题描述 ajax请求超时处理 后端Filter代码 前端通用ajax处理 非ajax请求超时跳转 Shiro 处理ajax请求拦截登录超时 配置全局ajax配置 $.ajaxSetup({ complete:function(XMLHttpRequest,textStatus){ if(textStatus=="parsererror"){ $.messager.ale

  • 使用Shiro实现登录成功后跳转到之前的页面

    这个问题是之前在做登录注册模块时遇到的需求,如何用户直接访问登录页面,可以控制直接跳到首页,但是如果是用户没有登录直接访问了购物车等需要经过身份认证的页面,或者是因为session超时,用户需要重新登录,那么这时跳回之前的页面就是提升用户体验的事情.实现此功能比较好的方法是用ajax的方式登陆,这样直接在当前页面弹窗让用户登录既可,二是把用户未登录前的url存在session中,login成功之后先检查session中是否存在这样的一个url.下面通过一段代码给大家分享下: 项目中集成了shir

  • Shiro中session超时页面跳转的处理方式

    目录 session超时页面跳转的处理 问题描述 ajax请求超时处理 非ajax请求超时跳转 一个判断session是否过期的小技巧 1.session其实就是一个Map 2.session的过期时间是从什么时候开始计算的? 3.设置session的失效时间 4.如何判断session过没过期 session超时页面跳转的处理 问题描述 shiro在管理session后,在session超时会进行跳转,这里有两种情况需要考虑,一种是ajax方式的请求超时,一种页面跳转请求的超时. 本文从这两个

  • Android编程中Intent实现页面跳转功能详解

    本文实例讲述了Android编程中Intent实现页面跳转功能.分享给大家供大家参考,具体如下: 安卓四大组件:Activity.Service.Broadcast Receiver.Content Provider Intent实现页面之间跳转 1.无返回值 startActivity(intent) 2.有返回值 startActivityForResult(intent,requestCode); onActivityResult(int requestCode,int resultCod

  • 对vue2.0中.vue文件页面跳转之.$router.push的用法详解

    vue2.0在使用的过程中, .vue文件之间的跳转,在template中的常见写法是: <router-link to="/miniCard/statement/horizon"> <button class="btn btn-default colorDe">继续</button> </router-link> 但是有时的需求是页面不直接跳转,有确认弹框或者其他事件,此时就需要在js中设置跳转,常用的一种方法是 .

  • Javascript页面跳转常见实现方式汇总

    本文实例总结了Javascript页面跳转常见实现方式.分享给大家供大家参考,具体如下: 概述 相信很多Web开发者都知道,在开发Web程序的时候,对于页面之间的跳转,有很多种,但是有效的跳转则事半功倍,下面就是我在平时的开发过程中所用到的一些JavaScript跳转方式,拿出和大家共享一下. 第一种:直接跳转加参数 <script language="javascript" type="text/javascript"> window.location

  • vue 页面跳转的实现方式

    一.this.$router.push() 1.vue <template> <div id='test'> <button @click='goTo()'>点击跳转4</button> </div> </template> 2.script //跳转前页面传参数: goTo(item) { //storageData中数据用于跳转到下一个页面之后,进行返回时能够返回到跳转之前的页面 let storageData = { searc

  • vue 使用vuex在页面跳转的实现方式

    目录 vue 使用vuex在页面跳转 第一种方式:使用 router 动态路由传参,将需要的数据带过去 第二种方式:使用vuex vuex 页面跳转参数存储获取 vue中我们用于页面跳转有三种方式 首先需要 接收页面 vue 使用vuex在页面跳转 学习时候碰到的需求场景:我的音乐列表,点击一个音乐项跳转到音乐详情页 第一种方式:使用 router 动态路由传参,将需要的数据带过去 音乐列表页组件: 音乐详情页组件: 音乐列表页通过selectSong方法传参,在音乐详情页的挂载完成里面将数据赋

  • springboot2中session超时,退到登录页面方式

    目录 session超时退到登录页面 1.首先在springboot中追加配置session的超时时间 2.登录成功接口中把用户信息追加session中 3.在WebMvcConfig中配置拦截规则和重定向规则 4.实现拦截器,先跳转到超时页面 5.在超时页面让用户等待几秒钟 session超时的问题 session超时退到登录页面 最近发现使用的工程居然没有session超时机制,功能太欠缺了,现在把追加方法分享出来,里面有一些坑,大家自由使用. 1.首先在springboot中追加配置ses

  • 详解SpringBoot中Session超时原理说明

    一:前言: 最近支付后台登录一段时间后如果没有任何操作,总是需要重新登录才可以继续访问页面,出现这个问题的原因就是session超时,debug代码后发现session的超时时间是1800s.也就是说当1800秒内没有任何操作,session就会出现超时现象.那这个超时时间是如何设置的呢?然后该如何重新设置此超时时间呢?系统又如何判断session超时的呢?接下来就一一进行解答. 二:系统session超时时间如何默认的? 说明:获取session超时时间的方法为"request.getSess

  • iOS开发中ViewController的页面跳转和弹出模态

    ViewController 页面跳转 从一个Controller跳转到另一个Controller时,一般有以下2种: 1.利用UINavigationController,调用pushViewController,进行跳转:这种采用压栈和出栈的方式,进行Controller的管理.调用popViewControllerAnimated方法可以返回. 复制代码 代码如下: PickImageViewController *ickImageViewController = [[PickImageV

  • Angular中$state.go页面跳转并传递参数的方法

    遇到一个页面跳转的时候,在跳转后的页面获取跳转前页面的数据,我想到用一种是localstorage,一种用broadcast和on,然后老大说不用这么麻烦,既然都$state.go了直接带参数,这次就介绍一下$state.go页面跳转传递参数. 1.路由页面(注意这里要在路由上添加一个参数用于传递数据,不然在页面跳转的时候会filter) .state("home.workpiece",{ // 跳转前的页面 url:"/workpiece", views: { h

随机推荐