• Shiro中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) + '<br/>err1:' + JSON.stringify(err1) + '<br/>err2:' + JSON.stringify(err2),
                    large : true
                });
            }
        });
    
        return result;
    }

    非ajax请求超时跳转

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

    重载的jquery.fn.load方法如下,注意beforeSendresponseText.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方法,该方法统一处理了超时跳转。

  • 相关阅读:
    eclipse基础环境配置和svn、maven的配置以及maven的安装
    KindEditor 上传图片浏览器兼容性问题
    FastDFS 工具类实现文件上传_02
    FastDFS 实现图片上传_01
    jvm 堆、栈 、方法区概念和联系
    jvm 虚拟机的组成部分
    利用jQuery实现CheckBox全选/全不选/反选
    FastDFS架构
    Nginx 实现负载均衡
    Nginx 实现反向代理
  • 原文地址:https://www.cnblogs.com/zhaoyan001/p/7714632.html
Copyright © 2020-2023  润新知