Spring ModelAttribute показывает старое значение после выхода из системы

Я разрабатываю приложение с использованием Spring. У меня проблема с входом и выходом. Я вошел в приложение, используя учетные данные для входа (например, имя пользователя: john, пароль: doe) и перешел на страницу администратора, а затем вышел из приложения. Но на этот раз я использовал другие учетные данные для входа (например, имя пользователя: jack, пароль: белый) для входа в систему. Когда я перехожу на страницу администратора и отлаживаю свое приложение, @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;
    }

}

person vtokmak    schedule 02.09.2013    source источник


Ответы (2)


Удалить эту аннотацию

@SessionAttributes({"myUser"})
person Diptopol Dam    schedule 02.09.2013
comment
Я удаляю аннотацию @SessionAttributes и @ModelAttribute(value = "myUser") User loggedInUser, я использовал HttpServletRequest вместо @ModelAttribute, это решило. - person vtokmak; 02.09.2013

Во-первых, @SessionAttributes не предназначен для хранения данных в сеансе между разными контроллерами. Он предназначен для использования только для хранения данных для одного и того же контроллера между запросами. Если вы хотите хранить элементы в сеансе между запросами, сохраните их в сеансе самостоятельно и не полагайтесь на @SessionAttributes. Это также упоминается в javadoc аннотации (хотя, возможно, немного загадочный).

Если вы хотите удалить объект, кэшированный @SessionAttributes, вы не можете просто очистить сеанс, но вам придется использовать объект SessionStatus (который вы можете добавить в качестве аргумента), чтобы отметить использование этих объектов как завершенное.

Ваш метод выхода слишком многословен, простого вызова session.invalidate() должно быть достаточно, но я думаю, что это была одна из ваших попыток исправить ситуацию. Также, когда вы находитесь в контейнере Servlet 3.0, может быть достаточно просто вызвать request.logout() (или вызвать его вместе с session.invalidate())

Мой последний совет: используйте Spring Security вместо того, чтобы пытаться разработать собственное решение для обеспечения безопасности.

person M. Deinum    schedule 02.09.2013
comment
Большое спасибо @Deinum, я буду использовать Spring Security вместо собственного решения для обеспечения безопасности. Будет полезнее. - person vtokmak; 02.09.2013