Ajax Session Timeout處理

對於session過時跳轉的問題,很簡單,就是一個過濾器,而後判斷session爲空?跳轉:繼續。可是對於ajax的請求,須要作特殊處理,見下面代碼中的css

// 此處考慮ajax操做session過時的操做,若是ajax請求過程當中session過時,則指定過時狀態碼爲:911.
String requestType = req.getHeader("X-Requested-With");java

由於ajax請求的時候請求頭是:X-Requested-With,so咱們能夠根據該請求頭作session過時處理。jquery

下面是過濾器的實現,能夠做爲參考。ajax

package com.***.action.util;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 標題:SessionFilter.
 * 
 * 描述:session expire filter.
 * 
 * @author lgscofield.
 */
public class SessionFilter implements Filter {

    private final static Log LOGGER = LogFactory.getLog(SessionFilter.class);

    /**
     * 過濾器配置
     */
    private FilterConfig filterConfig;

    /**
     * 超時頁面
     */
    protected String sessionTimeOutPage = null;

    /**
     * 某些url前綴列表(如: /css/*, /js/*, /images/***...)
     */
    private List<String> ignoreURIs = new ArrayList<String>();

    /**
     * 靜態資源列表(如: *.css, *.js, *.jpg...)
     */
    private List<String> ignoreExts = new ArrayList<String>();

    /**
     * 個別動態資源(如: login.action, navigate.action, login.jsp...)
     */
    private List<String> ignoreActions = new ArrayList<String>();

    /**
     * Default Construct.
     */
    public SessionFilter() {
        super();
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        LOGGER.info("Init LogFilter Start.");
        this.filterConfig = filterConfig;
        // this.context = this.filterConfig.getServletContext();
        // startMonitor();

        // 某些URL前綴不予處理(例如 /img/***)
        String ignores = filterConfig.getInitParameter("ignore");
        if (ignores != null) {
            for (String ig : StringUtils.split(ignores, ',')) {
                ignoreURIs.add(ig.trim());
            }
        }

        // 某些URL擴展名不予處理(例如 *.jpg)
        ignores = filterConfig.getInitParameter("ignoreExts");
        if (ignores != null) {
            for (String ig : StringUtils.split(ignores, ',')) {
                ignoreExts.add('.' + ig.trim());
            }
        }

        // 某寫頁面及Action不予處理(例如login.jsp,login.action)
        ignores = filterConfig.getInitParameter("ignoreActions");
        if (ignores != null) {
            for (String ig : StringUtils.split(ignores, ',')) {
                ignoreActions.add(ig.trim());
            }
        }

        LOGGER.info("Init LogFilter End.");
    }

    @Override
    public void destroy() {
        this.filterConfig = null;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
            ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        // HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper((HttpServletResponse) response);

        resp.setCharacterEncoding("UTF-8");
        HttpSession session = req.getSession(true);
        String requestUrl = req.getRequestURI();
        String redirectPath = req.getContextPath() + "/navigate.action";

        try {

            //過濾URL前綴
            /*
             * for (String ignoreURI : ignoreURIs) { if (requestUrl.startsWith(ignoreURI)) { chain.doFilter(req, resp);
             * return; } }
             */

            //過濾URL後綴
            for (String ignoreExt : ignoreExts) {
                if (requestUrl.endsWith(ignoreExt)) {
                    chain.doFilter(req, resp);
                    return;
                }
            }

            // 過濾登錄action/jsp
            for (String ingonAction : ignoreActions) {
                if (isContains(requestUrl, ingonAction)) {
                    chain.doFilter(req, resp);
                    return;
                }
            }

            if (requestUrl.endsWith("/portal/") || requestUrl.endsWith("/portal")) {
                resp.sendRedirect(redirectPath);
                return;
            }
        } catch (SecurityException e) {
            String loginPage = req.getContextPath() + URLEncoder.encode(requestUrl, "utf-8");
            resp.sendRedirect(loginPage);
        }

        // 驗證session是否過時
        Object user = session.getAttribute("userInfo");
        if (user == null) {
            
            // 此處考慮ajax操做session過時的操做,若是ajax請求過程當中session過時,則指定過時狀態碼爲:911.
            String requestType = req.getHeader("X-Requested-With");
            if (!StringUtils.isEmpty(requestType) && requestType.equalsIgnoreCase("XMLHttpRequest")) {
                resp.setStatus(911);
                resp.setHeader("sessionstatus", "timeout");
                resp.addHeader("loginPath", redirectPath);
                return;
            } else {
                // wrapper.sendRedirect(redirectPath);
                resp.sendRedirect(redirectPath);
                return;
            }
        } else {
            chain.doFilter(request, response);
            return;
        }
    }

    public static boolean isContains(String container, String regx) {
        boolean result = false;

        if (container.indexOf(regx) != -1) {
            return true;
        }
        return result;
    }

}

最後就是頁面上的處理了,此處應用了jquery全局事件處理機制:apache

$(function(){
    $.ajaxSetup({
        contentType: "application/x-www-form-urlencoded;charset=utf-8",
        cache: false,
        complete: function(XHR, TS){
            var resText = XHR.responseText;
            var sessionstatus = XHR.getResponseHeader("sessionstatus");
            var loginPath = XHR.getResponseHeader("loginPath");
            if (911 == XHR.status && "timeout" == sessionstatus) {
                // 此處使用了開源的消息確認框 
                $.messager.confirm('session過時', '您的會話已通過期,請從新登錄後繼續操做!', function(confirm){
                    if (confirm) {
                        window.location.replace(loginPath);
                    }
                });
                // 也能夠使用下面的原生js的確認框,若是確認則跳轉
                if(window.confirm('session過時', '您的會話已通過期,請從新登錄後繼續操做!')) {
                    window.location.replace(loginPath);
                }
                return;
            }
        }
    });
});
相關文章
相關標籤/搜索