0

我正在使用 Spring 开发一个应用程序。我在登录和注销时遇到问题。我使用登录凭据(例如用户名:john,pass:doe)登录应用程序并转到管理页面,然后从应用程序中注销。但是这次我使用了不同的登录凭据(例如用户名:jack,pass:white)进行登录。当我转到管理页面并@ModelAttribute(value = "myUser") User loggedInUserAdminController显示旧用户值时调试我的应用程序时。我不明白为什么会这样。任何人都可以帮忙吗?

我的源代码如下:

@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;
    }

}
4

2 回答 2

2

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

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

您的注销方法是冗长的方式,只需调用session.invalidate()就足够了,但我想这是您修复问题的尝试之一。此外,当您在 Servlet 3.0 容器上时,只需调用request.logout()就足够了(或与 一起调用session.invalidate()

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

于 2013-09-02T09:23:47.853 回答
2

删除此注释

@SessionAttributes({"myUser"})
于 2013-09-02T11:06:50.617 回答