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已经过期"); 
} 
}

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

Shiro中session超时页面跳转的处理方式的更多相关文章

  1. HTML5 Web缓存和运用程序缓存(cookie,session)

    这篇文章主要介绍了HTML5 Web缓存和运用程序缓存(cookie,session),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. iOS Swift上弃用后Twitter.sharedInstance().session()?. userName的替代方案

    解决方法如果您仍在寻找解决方案,请参阅以下内容:

  3. 使用Fabric SDK iOS访问Twitter用户时间线

    我试图在这个问题上挣扎两天.我正在使用FabricSDK和Rest工具包,试图为Twitter使用不同的RestAPIWeb服务.我可以使用具有authTokenSecret,authToken和其他值的会话对象的TWTRLogInButton成功登录.当我尝试获取用户时间线时,我总是得到失败的响应,作为:{“errors”:[{“code”:215,“message”:“BadAuthentic

  4. ios – 如何从Apple Watch调用iPhone上定义的方法

    有没有办法从Watchkit扩展中调用iPhone上的类中定义的方法?根据我的理解,目前在Watchkit和iPhone之间进行本地通信的方法之一是使用NSUserDefaults,但还有其他方法吗?

  5. ios – 如何将视频从AVAssetExportSession保存到相机胶卷?

    在此先感谢您的帮助.解决方法只需使用session.outputURL=…

  6. ios – 使用AVCaptureSession sessionPreset = AVCaptureSessionPresetPhoto拉伸捕获的照片

    解决方法所以我解决了我的问题.这是我现在使用的代码,它工作正常:…重要的输出imagaView:一些额外的信息:相机图层必须是全屏,并且outputimageView也必须是.我希望这些对某些人来说也是有用的信息.

  7. 我可以在iOS中自定义Twitter工具包的登录按钮吗?

    我已经下载了Twitter工具包框架并添加了用Twitter登录的代码.但是,我不希望登录按钮看起来像那样.我想要一个用于登录的自定义按钮.我能这样做吗?我只想使用这个框架,因为这也适用于iOS系统帐户.解决方法根据document:在按下按钮中添加代码:Objective-C的迅速

  8. ios – AVCaptureSession条形码扫描

    解决方法以下是我所拥有的项目代码示例,可以帮助您走上正确的轨道

  9. ios – 如何在Watch OS 2中引用不支持的框架

    有没有办法将框架链接到扩展名?

  10. ios7 – 在iOS 7中设置Alamofire中的自定义HTTP标头不工作

    解决方法我得到它的工作这对iOS7没有影响:然而,这将适用于iOS7和8:

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部