心急如焚啊,再次提问,session过期后,为什么数据还存在?!
在维护一个系统(struts1+jdbc),测试时在web.xml中设置了session过期时间是2分钟,首先,从登录页面中输入用户名、密码后,会到loginAction.do进行验证,然后导向页面index.jsp,2分钟后,index.jsp中的一些链接页面,如果点击的话,会显示请重新登录,session过期的一个页面,但是,我只要一刷新index.jsp页面,这些链接马上又可以用了,这是loginAction.do的代码 :
public class LoginAction extends DispatchAction
{
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest req, HttpServletResponse res)
throws Exception
{
DynaActionForm myForm = (DynaActionForm)form;
Map map = myForm.getMap();
String loginName = map.get("loginName").toString().trim();
String password = map.get("password").toString().trim();
ILogin login = (ILogin)Class.forName(get(map, "loginImplClass")).newInstance();
login.setLoginParam(loginName, password);
try
{
LoginResult result = login.login();
……(这里就是一些赋值操作)
LoginInfo loginInfo = result.getLoginInfo();
HttpSession session = req.getSession(true);
session.setAttribute("sUserName", loginInfo.getUserName());
session.setAttribute("sDeptName", loginInfo.getDeptName());
String key = session.getId();
……(这里是一些赋值操作 )
synchronized(getServlet().getServletContext())
{
try{
javax.servlet.GenericServlet slt = getServlet();
javax.servlet.ServletContext sc = slt.getServletContext();
((Hashtable)(sc.getAttribute("aVisitedUser"))).put(key, loginInfo);
beidian.com.commonpub.UserManager.onlineUser.put(key, loginInfo);
}
catch(Exception e)
{
logger.info("aOnlineUser", e);
e.printStackTrace();
}
}
}
catch(LoginException le)
{
return mapping.findForward("failed");
}
catch(LockException le)
{
return mapping.findForward("locked");
}
return mapping.findForward("success");
}
}
其中beidian.com.commonpub.UserManager的代码如下:(这个代码应该没什么吧)
public class UserManager {
public static java.util.Hashtable onlineUser = new java.util.Hashtable();
public UserManager() {
}
public static void main(String[] args) {
UserManager usermanager = new UserManager();
}
}
请各位高人指点……
[解决办法]
我觉得:
虽然 session 过期了, 但是数据依然存在缓存中. 它可能使用的获得 session 的方式可能是 true 的形式, 就是没有session我就重新申请一个.
解决办法:
1. 写一个 session 销毁监听, 当 destory 时, 在代码中我们将用户的信息从 session 中 remove 掉.
3. 最重要的一步, 写一个 servlet 过滤器, 对指定的资源进行过滤, 在这段代码中, 我们使用以下几步
1),HttpServletRequest httpRequest = (HttpServletRequest)request;
HttpSession session = httpRequest.getSession(false);
注意这个参数是 false, 就是当 session 不存在的时候会返回 null, 不会再申请新的 session.
2),
if (session!=null){ if (session.getAttribute("user")!=null) { isLogin = true; } }
[解决办法]
如果你login后是forward到index.jsp,刷新index.jsp就相当于重新登陆了一次,当然就能继续显示了。登录后最好用redirect
[解决办法]
呃…… 之前看过servlet规范,就算session过期,如果使用该session的所有的servlet service()方法没有执行完毕,那么过期时间的无效化就不会产生作用。恐怕楼主要研究一下DispatchAction中的源码才能找到满意的答案了。还有String key = session.getId(); 这条语句也让人在意,因为后面将其引用到了servletcontext。不知道有没有影响。哈哈。说的话跟没说的一个样。
[解决办法]
在JSP页面加下面清除缓存代码试下看看:
<%
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
%>
[解决办法]
刷新的时候,你之前post提交的数据也会再次提交,当然可以取到用户名和密码了。
[解决办法]
刷新一下,就重复提交一下之前那个表单。所有你得用令牌来阻止重复提交.
[解决办法]
进入创建前的Actionpublic final class EnterNewProjectPageAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { saveToken(request); return (mapping.findForward("createproject_jsp")); }}// 创建Actionpublic final class CreateProjectAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { if(isTokenValid(request)){ resetToken(request); CreateProjectForm createProjectForm=(CreateProjectForm)form; Project newProject=createProjectForm.getProject(); newProject.setCreateTime(Util.getCurrTime()); ProjectService.create(newProject); } else{ System.out.println("重复提交"); } ProjectUtil.setupPages(0,request); return (mapping.findForward("projects_jsp")); }}
[解决办法]
哈哈。。。我觉得yys79 的答案是正解。。。你一刷新又发送了一次表单数据进行了验证,
楼主可以在Action中输出语句试一下...
我也觉得应该用重定向到跳转页面,而不该用转发。。forward...
[解决办法]
1、加个防重复提交代码,Struts里面有的
2、Action中跳转时,不要使用mapping.findForward()方式跳转,跳转时候,用return new ActionForward("URL",true);
3、在页面上加上判断session,为空,则session失效
[解决办法]
楼主应该好好的学习一下forward和Redirect这两种转发方式,之前我们的项目也是遇到像你这样的问题。
有2种方式去解决,
1.登陆验证完毕后,将用户信息放入Session,再重定向,也就是Redirect
2.我自己写了一个类似的令牌机制
package cn.net.ssd.pubUtil;import java.util.ArrayList;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;/** * * @author 大米辉 Mar 26, 2009 * @project SSD_ZH_ALARM * */public class CheckToken{ /** * 检测是否是重复提交 * @param request * @param reset 保存令牌 * @return *//* public static boolean isTokenValid(HttpServletRequest request,boolean reset){ boolean rs=true; HttpSession session =request.getSession(); Object token=session.getAttribute("isValid"); if(token!=null){ String isValid=token.toString(); if(isValid.equals("1")){ rs=true; } }else{ rs=false; } if(reset){ saveToken(request); } return rs; } *//** * 保存令牌 * @param request *//* public static void saveToken(HttpServletRequest request){ HttpSession session =request.getSession(); session.setAttribute("isValid","1"); } *//** * 重置Token * @param request *//* public static void resetToken(HttpServletRequest request){ HttpSession session =request.getSession(); if(session.getAttribute("isValid")!=null){ session.removeAttribute("isValid"); } }*/ private static final String TOKEN_LIST_NAME = "tokenList"; public static final String TOKEN_STRING_NAME = "token"; @SuppressWarnings("unchecked") private static ArrayList<String> getTokenList(HttpSession session) { Object obj = session.getAttribute(TOKEN_LIST_NAME); if (obj != null) { return (ArrayList<String>) obj; } else { ArrayList<String> tokenList = new ArrayList<String>(); session.setAttribute(TOKEN_LIST_NAME, tokenList); return tokenList; } } /** * 保存令牌字符串 * @param tokenStr * @param session */ private static void saveTokenString(String tokenStr, HttpSession session) { ArrayList<String> tokenList = getTokenList(session); tokenList.add(tokenStr); session.setAttribute(TOKEN_LIST_NAME, tokenList); } /** * 得到令牌字符串 * @param tokenStr * @param session */ private static String generateTokenString(){ return new Long(System.currentTimeMillis()).toString(); } /** * Generate a token string, and save the string in session, then return the token string. * * @param HttpSession * session * @return a token string used for enforcing a single request for a particular transaction. */ public static String getTokenString(HttpSession session) { String tokenStr = generateTokenString(); saveTokenString(tokenStr, session); return tokenStr; } /** * check whether token string is valid. if session contains the token string, return true. * otherwise, return false. * * @param String * tokenStr * @param HttpSession * session * @return true: session contains tokenStr; false: session is null or tokenStr is id not in session */ public static boolean isTokenStringValid(String tokenStr, HttpSession session) { boolean valid = false; if(session != null){ ArrayList<String> tokenList = getTokenList(session); if (tokenList.contains(tokenStr)) { valid = true; tokenList.remove(tokenStr); } } return valid; } public static boolean isTokenValid(HttpServletRequest request){ return isTokenStringValid(request.getParameter(CheckToken.TOKEN_STRING_NAME), request.getSession()); }}