• Java Web Application使Session永不失效(利用cookie隐藏登录)


      在做 Web Application 时,因为 Web Project 有 session 自动失效的问题,所以如何让用户登录一次系统就能长时间运行三个月,就是个问题。

      后来,看到 session 失效的拦截器代码,就猜想能否通过拦截器来实现。

      查资料发现可行:用户登录时将帐号密码存入cookie,cookie可以存储1年至更久,当session失效被拦截时,在拦截器内读取cookie 中的用户名和密码后再登录。(登录过程隐藏对用户不可见)。

      在实践过程中遇到个问题: 在拦截器内重新实现登录过程(包括写session),此时写session是成功的,但是返回被拦截器拦截的 Action 方法内时,Action 内的方法读取的session却是空的。(2017-06-12 更新,出错原因是保存的sesion和读取的session分别是Strut2包装的session和JSP/Sevlert内置的session,导致读取为空,参见)


     方法一:设置 session-timeout 参数值

    最简单的办法是,在Java Web 中可通过设置 web.xml 中的 session-timeout 为 -1 即可实现 session 永不失效。

    Java Web中有关 Session 失效的设置有三处:

    1. 页面或者代码内通过 session.setMaxInactiveInterval

    2. 项目的web.xml 中的 session-timeout (验证有效)

    3. Tomcat 的 server.xml 中的  (该方法本文未验证,网上搜集)

    <Context path="/livsorder" docBase="/home/httpd/html/livsorder" 
      defaultSessionTimeOut="3600" isWARExpanded="true" 
      isWARValidated="false" isInvokerEnabled="true" 
      isWorkDirPersistent="false"/> 
    

    4. Tomcat 的 web.xml 中的 (该方法本文未验证,网上搜集)

    <session-config>  
            <session-timeout>30</session-timeout>  
    </session-config>  

    分别对应:

    1. 当前会话生效

    2. 整个Web应用有效

    3. 不详

    4. 不详

    设置产生效果的优先顺序很显然是:1 -> 2 ,没有指明就是用默认设置。

    另外: setMaxInactiveInterval的参数是秒,session-config当中配置的session-timeout是分钟。  设置session-timeout是永久有效。【setMaxInactiveInterval(-1)也是元永久有效(本人未测试)】。测试是否是永久有效很简单,只需要在本地测试(localhost)时,将本机的时间调整为几个月之后即可。

    但在实际使用中并不理想,因为超出 tomcat 的默认是 30 分钟,如果修改 tomcat 默认值,会影响其他项目不说,也很容易遗忘,对今后产生莫名其妙的问题。


    方法二:使用 Struts2 拦截器

      原理:在使用了 Struts 框架的代码中,使用拦截器,测试Session 是否为空,若是空,利用 cookie 里藏的用户名和密码进行登录,并保存到 session 中。

    代码:(本人亲测,实际使用)

    1. 登录保存到 Struts2 包装的 session中(注意,前后session要对应)

     根据项目需要,可决定是否加密。我示例未加密。

    // 你的登录方法内部
    // user 是登录成功后的用户对象
    ActionContext.getContext().getSession().put("user", user);
    
    //创建或覆盖COOKIE
    Cookie ckName = new Cookie("jsjgUserName", username);
    Cookie ckPwd = new Cookie("jsjgUserPwd", password);
    ckName.setMaxAge(365*24*60*60);
    ckPwd.setMaxAge(365*24*60*60);
    response.addCookie(ckName);
    response.addCookie(ckPwd);

    2. 拦截器代码

    package com.tools;
    
    
    import java.util.Map;
    
    import javax.servlet.ServletContext;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpSession;
    
    import org.apache.struts2.ServletActionContext;
    import org.apache.struts2.StrutsStatics;
    import org.springframework.context.ApplicationContext;
    import org.springframework.web.context.support.WebApplicationContextUtils;
    
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.Interceptor;
    import com.zhzx.class_entity.User;
    import com.zhzx.service.UserService;
    
    @SuppressWarnings("serial")
    public class MyInterceptor implements Interceptor {
        
    
    
        public void destroy() {
        }
    
        public void init() {
        }
    
        public String intercept(ActionInvocation actionInvocation) throws Exception {
    
            // 确认Session是否过期
            Map strutSession = actionInvocation.getInvocationContext().getSession();
            Cookie[] cookies = ServletActionContext.getRequest().getCookies();
            
            User us=(User) strutSession.get("user");
            String userName = "";
            String userPwd = "";
            
            if (us!=null&&!"".equals(us)) {
                return actionInvocation.invoke();
            } else {
                //从cookie得到登录账户
                if(cookies != null){
                    for(Cookie cookie:cookies){
                        if(cookie.getName().equalsIgnoreCase("jsjgUserName")){
                            userName = cookie.getValue();
                            System.out.println(userName);
                        }else if(cookie.getName().equalsIgnoreCase("jsjgUserPwd")){
                            userPwd = cookie.getValue();
                        }
                    }
                    //登录
                    if(userName != null && userPwd != null){
                        
                        //因项目使用了SSH,所以这里是获取Spring管理的bean
                        ServletContext context = (ServletContext) actionInvocation.getInvocationContext().get(StrutsStatics.SERVLET_CONTEXT); 
                        ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(context);
                        UserService userService = (UserService)ctx.getBean("UserService");
                        
                        //是否注入成功
                        System.out.println(userService);
                        
                        //登录并放入Strtu2包装的session
                        User user=userService.Login(userName);
                        if(user != null && user.getPassword().toLowerCase().equals(userPwd.toLowerCase())){
                            strutSession.put("user", user);
                        }
                        
                        return actionInvocation.invoke();
                    }
                    
                    
                }
                return "timeout";
            }
        }
    
    
    }

    然后拦截器按照常规方法使用即可。拦截器可以看看 Struts in Action ,Struts实战之类的书及PDF,有详细的讲解和例子。

    吐槽:Java是太庞杂了,框架多不说,使用起来也方法各样,一会儿流行配置文件,一会儿流行注解,一会SSH,一会SSM,一会Sping MVC。

    我就想说这不都是自己折腾自己么,学习成本不是成本么,发明出这么多轮子,软件行业不还是加班。旧的软件项目不还是要维护。

    Java体系真是自己折腾自己,真心无爱了。 

    我觉得框架只是工具,就像武侠世界里,真正的高手是用什么工具都可以杀人于无形,那管你是用很多人鄙视的 ASP.NET 还是自以为很牛逼的Java Web,

    甲方和老板关心的无非是你做完了么,做的好看么,是不是?

    程序员,工程师们还是消停点好,多关心下自己的健康和身边的人不好么?

  • 相关阅读:
    mybaits错误解决:There is no getter for property named 'id' in class 'java.lang.String'(转)
    Tomcat配置虚拟路径
    FireFox背景亮度修改
    简单的百度贴吧爬虫实现(urllib)
    python知识总结
    QT-- MainWindow外的cpp文件调用ui
    数据结构--栈的实现
    数据结构-- 队列的实现
    经典排序算法---归并排序
    经典排序算法---希尔排序
  • 原文地址:https://www.cnblogs.com/muyun/p/5345118.html
Copyright © 2020-2023  润新知