代码之家  ›  专栏  ›  技术社区  ›  vtokmak

Spring ModelAttribute在注销后显示旧值

  •  0
  • vtokmak  · 技术社区  · 12 年前

    我正在使用Spring开发一个应用程序。我在登录和注销方面遇到了麻烦。我使用登录凭据(例如,用户名:john,密码:doe)登录应用程序,然后转到“管理”页面,然后从应用程序注销。但这次我使用了不同的登录凭据(例如用户名:jack,密码:white)进行登录。当我转到“管理”页面并调试我的应用程序时 @ModelAttribute(value = "myUser") User loggedInUser AdminController 显示旧用户价值。我不明白为什么会发生这种情况。有人能帮忙吗?

    我的源代码如下:

    @Controller
    @RequestMapping("/LoginController")
    @SessionAttributes({"myUser"})
    public class LoginController 
    {
        private static String LOGIN_URL         = "login/login_";
        private static String INDEX_URL         = "main/index";
    
        @Autowired
        private IUserService userService    = null;
    
        @RequestMapping("/login")
        public ModelAndView login(@RequestParam(value="userName", required=false) String argUserName, @RequestParam(value="password", required=false) String argPassword, HttpServletRequest req)
        {
    
            ModelAndView modelAndView = new ModelAndView();
    
            // Assume argUserName and argPassword not null
            User loginUser = this.userService.getUser(argUserName, argPassword);
    
            HttpSession ses = req.getSession();
    
            // Assume loginUser not null
            ses.setAttribute("myUser", loginUser);
    
            modelAndView.setViewName(LoginController.INDEX_URL);
    
            return modelAndView;
        }
    
        @RequestMapping("/logout")
        public String logout(HttpServletRequest argReq, HttpServletResponse argResp) throws ServletException, IOException
        {
            HttpSession session = argReq.getSession(false);
    
            Enumeration<?> attributeNames = session.getAttributeNames();
            while(attributeNames.hasMoreElements())
            {
                String attrName = (String)attributeNames.nextElement();
    
                if(session.getAttribute(attrName) != null)
                {
                    session.setAttribute(attrName,null);
                    //session.removeAttribute(attrName);
                    attributeNames = session.getAttributeNames();
                }
            }
            // close session
            session.invalidate();
    
            return LoginController.LOGIN_URL;
        }
    }
    

    管理员控制器

    @Controller
    @RequestMapping("/AdminController")
    @SessionAttributes({"myUser"})
    public class AdminController 
    {
        private static String SETTINGS_PAGE = "settings/index";
    
        @RequestMapping("/index")
        public ModelAndView index(@ModelAttribute(value = "myUser") User loggedInUser, HttpSession ses)
        {
            ModelAndView modelAndView = new ModelAndView();
            Map<String, Object> map = new HashMap<String, Object>();
    
            map.put("loggedInUserId", loggedInUser.getUserID());
            map.put("userName", loggedInUser.getUserName());
    
            modelAndView.addAllObjects(map);
    
            modelAndView.setViewName(AdminController.SETTINGS_PAGE);
            return modelAndView;
        }
    
    }
    
    2 回复  |  直到 12 年前
        1
  •  2
  •   Diptopol Dam    12 年前

    删除此批注

    @SessionAttributes({"myUser"})
    
        2
  •  2
  •   M. Deinum    12 年前

    对于启动器 @SessionAttributes 不是为了在不同控制器之间的会话中存储数据而设计的。它的预期用途只是在请求之间存储同一控制器的数据。如果您想在请求之间的会话中存储项目,请将它们自己存储在会话中,不要依赖@SessionAttributes。中也提到了这一点 the javadoc 注释(尽管可能有点神秘)。

    如果要删除缓存的对象 @会话属性 您不能简单地清除会话,但必须使用 SessionStatus 对象(您可以将其添加为参数),以标记这些对象的使用完成。

    您的注销方法过于冗长,只需调用 session.invalidate() 应该足够了,但我想这是你试图解决的问题之一。此外,当您在Servlet 3.0容器上时,只需调用 request.logout() 可能就足够了(或将其与 session.invalidate()会话无效() )

    我的最后建议是 Spring Security 而不是尝试开发自己的安全解决方案。

    推荐文章