同一Tomcat下session共享及用户验证方案

背景介绍

本文实际情况如下:原来有一个内部系统old,不过由于年代久远,代码老而旧,新增了一个系统的模块不想在原系统上增加。于是乎新写了一个项目new,放在与原项目同一个tomcat下。由于原系统已经有了完整的用户登录权限等内容,想通过原系统登录,登录后直接一个菜单新开窗口跳转到新系统。

问题分析:

问题在于:如何实现用户在old登录,然后跳转到new系统中,并带有用户的信息的验证。
实现方式:(1)可以做一个单点登录,需要对old系统改造增加相应的接口,比较麻烦内容较多。【不采取】
    (2) 通过session共享,每次请求去old系统验证session信息。【采取】

解决方案:

  • tomcat配置session共享:
修改server.xml文件的内容

		
		 
      
crossContext属性的意思是:如果设置为true,你可以通过ServletContext.getContext() 调用另外一个WEB应用程序,获得ServletContext 然后再调用其getAttribute() 得到你要的对象。【每一个web应用程序都有唯一一个ServletContext实例对象,被该web应用下面的每一个servlet共享。】
  • old系统session信息
用户登录old系统后,通过如下代码设置session信息岛ServletContext中
HttpSession session = request.getSession();
						session.setAttribute(Constant.USER, user);
						ServletContext context = session.getServletContext();
						context.setAttribute("userId"+user.getId(), session);
这里context.setAttrbute方法是方便多用户时,能够分别记录不同用户的session。
  • old系统添加跳转菜单
简单的页面添加一个跳转的url:
var url = "http://"+'<%=ip%>'+":"+'<%=port%>'+"/projectB/index.action?user_id="+userId;
            window.open(url);
       这里的ip.port就是在jsp中获取到的服务的IP端口,因为是在同一个tomcat下,肯定是相同的,projectB是new系统的上下文。
  • new系统中增加filter验证
新增一个filter,拦截new系统中所有的操作。其dofilter中伪代码如下:
@Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        //判断当前请求是否有user_id参数,如果有,说明是第一次从old系统跳转过来
        HttpSession session = request.getSession();
        String userIdStr = request.getParameter(Constant.USER_ID);
        if(ObjectUtils.isStringNotEmpty(userIdStr)){//第一次跳转过来,把用户信息放入session
            UserInfoService userInfoService = AppContext.getBean("userInfoService");
            UserInfo userInfo = userInfoService.findUserById(Long.parseLong(userIdStr));
            if(userInfo != null){
                session.setAttribute(Constant.USER,userInfo);
                session.setAttribute(Constant.USER_ID,userInfo.getId());          
            }
        }else{//从session中取用户ID
            userIdStr = session.getAttribute(Constant.USER_ID)+"";
        }

        //拿到old系统放入ServletContext中的当前用户的session信息
        ServletContext context = session.getServletContext();
        ServletContext projToolContext = context.getContext("/projectA");
        HttpSession userSession = null;
        if(ObjectUtils.isStringNotEmpty(userIdStr)){
            userSession = (HttpSession) projToolContext.getAttribute("userId"+userIdStr);
        }
        //判断当前session是否过期
        Boolean userLoginStauts = null;
        try{
            if(userSession == null){
                userLoginStauts = false;
            }else{
                userLoginStauts = userSession.getAttribute(Constant.USER) != null;
            }
        }catch (IllegalStateException e){
            log.info("java.lang.IllegalStateException: getAttribute: Session already invalidated,use this exception judge user status");
            userLoginStauts = false;
        }
        if(!userLoginStauts){//session过期,即用户未登录,返回相应的信息
            if (request.getHeader("x-requested-with") != null
                && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {// Ajax请求
                response.setCharacterEncoding("utf-8");
                PrintWriter printWriter = response.getWriter();
                AjaxResponse ajaxResponse = new AjaxResponse();
                ajaxResponse.setResult(-1);
                ajaxResponse.setResultMsg("用户未登录");
                printWriter.write(JSON.toJSONString(ajaxResponse.getData()));
                return;
            } else {// 网页请求,跳转至首页
                response.sendRedirect("http://"+request.getServerName()+":"+request.getServerPort()+"/projectA/login.jsp");
                return;
            }
        }
        filterChain.doFilter(servletRequest,servletResponse);
    }

总结:

这种方式适合一些小的系统,自己内部使用,不建议大的系统使用这种方式,虽然可以解决一些用户验证、session共享的问题,未暴露的问题不知道还有多少。这里仅仅是记录下,如有类似的简单场景可以使用。因为: 没有最好的方案,只有最合适的方案

你可能感兴趣的:(JAVA基础大法,------【经验总结】)