zoukankan      html  css  js  c++  java
  • java-同一用户顶替操作(session过期或无效)

    同一账号后者登录前者被强制退出:(可以通过监听器或过滤器进行监测session是否无效)

    首先根据输入的用户名和密码做验证,通过验证查询用户信息。在用户信息不为空的前提下,比较静态变量中的sessionid和浏览器session获取的getId(),判断两个值是否一致,若一致,则通过 正常走流程,若不一致,则返回登录页面,session设置msg,提示“账户失效或异地登录”;

    web.xml:

    <session-config>
            <session-timeout>180</session-timeout><!--session过期时间设置-->
    </session-config>

    controller:

        public static Map<HttpSession, String> loginSessionList = new HashMap<>();//保存当前登录的所有用户
    
        //登录方法
        @ResponseBody
        @RequestMapping(value = "/login", method = RequestMethod.POST)
        public ResponseResult login(User user, HttpServletRequest request,HttpSession session) {
              //.............................
                session.setAttribute("username", user.getLoginName());
                session.setAttribute("logoutType", "0");
                checkLoginSession(session,user.getLoginName());
                loginSessionList.put(session, user.getLoginName());
              //.............................  
        
         }
    
         /**
         * 检查用户是否已经登录
         * @param session
         * @param loginName
         * @return
         */
        private String checkLoginSession(HttpSession session,String loginName) {
            String checkValue = "0";
            HttpSession reSession = null;
            try {
                Set<HttpSession> keys = loginSessionList.keySet();
                for (HttpSession key : keys) {
                    if (loginSessionList.get(key).equals(loginName) && !session.equals(key)) {
                        //key.invalidate();//如果该用户名有登录,则使前者失效(适用于方法一)
                        key.setAttribute("logoutType", "1");
                        checkValue = "1";
                        reSession = key;
                        break;
                    }
                }
                if (checkValue.equals("1") && reSession != null) {
                    //防止用户直接关闭浏览器
                    loginSessionList.remove(reSession);
                }
            } catch (Exception e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            }
            return null;
        }

    参考链接:servlet/filter/listener/interceptor区别与联系

    方法一:(使用 HttpSessionListener进行监听)

    使用监听器监听对页面跳转不好进行控制

    web.xml:

    <!-- session监听  -->
        <listener>
              <listener-class>net.nblh.system.shiro.OnlineUserListener</listener-class><!--监听器类的路径-->
        </listener>

     OnlineUserListener:

    package net.nblh.system.shiro;
    
    import javax.servlet.http.HttpSession;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    import net.nblh.system.controller.SystemController;
    
    public class OnlineUserListener implements HttpSessionListener{
    
        /**
         * 监听session创建
         */
        @Override
        public void sessionCreated(HttpSessionEvent arg0) {
            // TODO 自动生成的方法存根
            
        }
    
        /**
         * 监听session销毁
         */
        @Override
        public void sessionDestroyed(HttpSessionEvent event){
            try {
                // TODO 自动生成的方法存根
                HttpSession session = event.getSession();
                // 取得登录的用户名
                String username = (String) session.getAttribute("username");
                SystemController.loginSessionList.remove(session);
                System.out.println(username + "退出。");
            } catch (Exception e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            }
            
        }
        
    }

    方法二:(使用Filter进行过滤)

    web.xml:

    <!-- session过滤器 -->
        <filter>
            <filter-name>sessionFilter</filter-name>
            <filter-class>net.nblh.system.shiro.SessionFilter</filter-class><!--过滤器类的路径-->
        </filter>
        <filter-mapping>
                <filter-name>sessionFilter</filter-name>
                <url-pattern>/*</url-pattern>
        </filter-mapping>

    SessionFilter:

    package net.nblh.system.shiro;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    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 net.nblh.system.controller.SystemController;
    import net.nblh.system.entity.SysConfigItemValue;
    import net.nblh.utils.StringUtils;
    
    /**
     * Session拦截器
     * @author lijd
     *
     */
    public class SessionFilter implements Filter {
    
        @Override
        public void destroy() {
            // TODO 自动生成的方法存根
    
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            try {
                // TODO 自动生成的方法存根
                HttpServletRequest httpRequest = (HttpServletRequest) request;
                HttpServletResponse httpResponse = (HttpServletResponse) response;
                HttpSession session = httpRequest.getSession();
    
                //异地顶替账号登录url
                String toLoginUrl = session.getServletContext().getContextPath()+"/system/tologin2";//列席人登录页面
                //session过期登录url
                String sessionLoginUrl = StringUtils.isNotEmpty(SysConfigItemValue.getValue("sessionOutTimeToURL"))?SysConfigItemValue.getValue("sessionOutTimeToURL"):toLoginUrl;
                String url = httpRequest.getRequestURI();
                String path = url.substring(url.lastIndexOf("/"));
                /*// 判断是否为ajax请求
                if (httpRequest.getHeader("x-requested-with") != null && httpRequest.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
                    //该请求是 AJAX 异步HTTP请求
                    if (session.getAttribute("shiroSavedRequest") != null && session.getAttribute("currentUser") == null) {
                        SystemController.loginSessionList.remove(session);
                        session.invalidate();
                        httpResponse.addHeader("sessionstatus", "timeOut");//Session已过期
                        httpResponse.addHeader("loginPath", sessionLoginUrl);
                        chain.doFilter(request, response);
                    }else {
                        chain.doFilter(request, response);// 不可少,否则请求会出错
                    }
                }*/
                if (path.indexOf("sessionTimeOut") != -1 && session.getAttribute("shiroSavedRequest") != null && session.getAttribute("currentUser") == null) {
                    SystemController.loginSessionList.remove(session);
                    session.invalidate();
                    //session过期
                    toLoginUrl(response,"会话已过期",sessionLoginUrl);
                }         
                else if(session.getAttribute("logoutType") != null && session.getAttribute("logoutType").equals("1")){
                    SystemController.loginSessionList.remove(session);
                    session.invalidate();
                    // logoutType=0:正常,logoutType=1:异地登录                
                    toLoginUrl(response,"用户已在别处登录",toLoginUrl);
                } else {
                    try {
                        chain.doFilter(request, response);
                    } catch (Exception e) {
                        SystemController.loginSessionList.remove(session);
                        session.invalidate();
                        toLoginUrl(response,"会话已过期!",sessionLoginUrl);
                    }
                }
            } catch (Exception e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            }
        }
    
        @Override
        public void init(FilterConfig arg0) throws ServletException {
            // TODO 自动生成的方法存根
    
        }
    
        /**
         * session无效后跳转指定路径
         * @param response
         * @param message
         * @param loginUrl
         */
        private void toLoginUrl (ServletResponse response,String message,String loginUrl) {
            String str = "<script language='javascript'>alert('"+ message +"');" + "top.location.href='" + loginUrl + "';</script>";
            response.setContentType("text/html;charset=UTF-8");// 解决中文乱码
            try {
                PrintWriter writer = response.getWriter();
                writer.write(str);
                writer.flush();
                writer.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    使用响应头进行JS控制:

    httpResponse.addHeader("sessionstatus", "timeOut");//Session已过期
    httpResponse.addHeader("loginPath", sessionLoginUrl);
    chain.doFilter(request, response);

    js:

    <script type="text/javascript">
    $(document).ajaxComplete(function(event, xhr, settings) {  
        if(xhr.getResponseHeader("sessionstatus")=="timeOut"){  
            if(xhr.getResponseHeader("loginPath")){
                alert("会话过期,请重新登陆!");
                window.location.replace(xhr.getResponseHeader("loginPath"));  
            }else{  
                alert("请求超时请重新登陆 !");  
            }  
        }  
    });  
    </script>
  • 相关阅读:
    Qt QChart 中 QValueAxis 和 QCategoryAxis 区别
    Qt QChart 绘制面积图 QAreaSeries
    Qt QChart 设置线条样式 虚线
    Qt 读取csv文件并且绘制折线图
    Qt comboBox控件的三种基本用法
    Qt QStringList 的学习笔记
    OpenYurt 联手 eKuiper,解决 IoT 场景下边缘流数据处理难题
    如何避免 Go 命令行执行产生“孤儿”进程?
    阿里巴巴代码平台架构的演进之路
    云原生演进趋势下传统数据库升级实践
  • 原文地址:https://www.cnblogs.com/lijianda/p/10686331.html
Copyright © 2011-2022 走看看