Нежелательные аргументы, разделенные запятыми, на метод контроллера Spring
Я вижу странную проблему с контроллером MVC Spring. Этот метод предназначен для установки пароля. Он принимает два параметра формы: "пароль" и "confirmPassword". При первом вызове формы это отлично работает - поля передаются методу.
Проблема возникает, когда форма отправляется второй раз. Если форма была неправильно заполнена в первый раз, пользователь был правильно отправлен на страницу формы и попросил снова ввести пароль. Однако аргументы метода неверны во второй попытке. Аргументы представляют собой список, разделенный запятыми, который включает в себя запись первой формы, объединенную со вторым.
Пример:
Сообщение первой формы с полем "пароль" имеет значение "abc". Аргумент метода "пароль" имеет значение "abc".
Второе сообщение формы с полем "пароль" и значением "xyz". Аргумент метода "пароль" имеет значение "xyz, abc".
Документы Spring MVC не показывают много полезного. Как-то старое сообщение формы запоминается и включается. У кого-нибудь есть опыт в решении этого вопроса?
Ниже приведен метод контроллера:
@RequestMapping(value = "/account/reset", method = RequestMethod.POST)
public String resetPassword(@RequestParam("password") String password,
@RequestParam("confirmPassword") String confirmPassword,
@RequestParam("hash") String hash, ModelMap model) throws EncryptionException
{
String userName = stringEncrypterService.decrypt(hash);
User user = userService.findUserByPath(userName);
if (!password.equals(confirmPassword))
{
model.put("hash", hash);
model.put("user", user);
model.put("error",
"The two passwords you entered below do not match. Please try again.");
return "users/resetPassword";
}
userService.updatePassword(user, password);
emailService.sendUserInfoChange(user);
return "redirect:/session/signin?passwordReset=true";
}
Update. Несколько респондентов предположили, что, возможно, в проблемных сообщениях есть дополнительные параметры URL или скрытые поля форм, что приводит к дублированию имен полей. Я подтвердил Фиддлеру, что это не так. Вот необработанный запрос с третьей попытки. (слегка отредактированный для удаления cookie сеанса).
POST http://wintest.foriodev.com/simulate/account/reset/ HTTP/1.1
Host: wintest.foriodev.com
Connection: keep-alive
Referer: http://wintest.foriodev.com/simulate/account/reset/
Content-Length: 73
Cache-Control: max-age=0
Origin: http://wintest.foriodev.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16
Content-Type: application/x-www-form-urlencoded
Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: AUTOLOGIN_TOKEN=xyz; SIMULATE_WORKER=wintest; JSESSIONID=xyz;
password=a&hash=xyz&confirmPassword=a&save=Reset+Password
Ответы
Ответ 1
Итак, через год я понял это.
Проблема заключалась в пользовательском перехватчике, который хранил кеш запросов в каждом запросе. Я делаю это так, что, когда пользователь войдет в систему, он вернется к предыдущему экрану. Но он совершенно не подходит для экрана "reset password".
Механизм заключался в том, что когда request.getParameter(Name) вызывается, SavedRequestCacheWrapper затем объединяет фактические параметры HTTP-запроса с сохраненными параметрами из этого последнего запроса.
Решение состоит в том, чтобы (а) этот перехватчик игнорировал экран пароля reset и (б) игнорировал все почтовые запросы, чтобы предотвратить такое конкатенацию значения этого типа запроса.
Другим респондентам, спасибо за все хорошие идеи. (И анонимному пользователю, который поставил щедрость на это - спасибо за то, что заставил меня вернуться и посмотреть еще раз.)
Ответ 2
Я думаю, причина этого в том, что
return " перенаправление:/session/signin? passwordReset = true";
С перенаправлением: структура использует технику перезаписи url, похожую на базовую response.sendRedirect(...) в сервлетах, и, следовательно, параметры, значения добавляются вместе с запросом к следующим последующим запросам и т.д..
Попробуйте использовать другой механизм, а не " перенаправление:"
Ответ 3
Если вы публикуете в третий раз, список тоже растет до трех? Это указывает на то, что проблема связана с сеансом пользователя. Или, если список остается в два, проблема возникает в запросе. Я предполагаю, что список вырастет до трех, поскольку информация, которую вы опубликовали у Fiddler, не показывает никаких признаков дублирования в запросе.
Чтобы подтвердить, что данные находятся в сеансе, проверьте его содержимое (например, печать в журнал, использование отладчика, печать на веб-странице в среде dev) для данных под теми же ключами - "пароль", хэш "и т.д.
Также см. этот другой ответ о том, почему данные могут быть в пользовательской сессии, например. вы где-то использовали аннотацию @SessionAttributes.
Ответ 4
Вы получите разделенные запятыми значения, если у вас есть несколько полей формы с тем же именем. Общей причиной этого является наличие скрытых входов и текстовых входов с тем же именем. В первый раз, когда страницы публикуются, скрытые входы будут пустыми, поэтому никаких запятых. Второе (и subsiquent) время сообщений страницы, скрытые входы будут иметь значения, поэтому вы получите запятые.
Ответ 5
Похоже, что старые значения каким-то образом отображаются как параметры GET, т.е. у вас есть <form action = ".../account/reset?password=abc">
во второй форме, или action
пуст, а URL второй формы - .../account/reset?password=abc
. Хотя я не могу найти ничего ответственного за это в вашем коде.
Ответ 6
Вы как-то указываете поля формы второй раз, когда возвращаетесь с шага проверки? Используйте Firebug или что-то подобное, чтобы проверить, что вы отправляете и/или публикуете на странице jsp (или аналогичной).
Ответ 7
Похоже, это может быть вызвано проблемой https://jira.springsource.org/browse/SEC-1258
"SavedRequestAwareWrapper вызывает проблемы с 3.0 M2 в сочетании с Spring MVC"
Ответ 8
В моем случае я связал скрытое поле с неиспользуемым путем. Удаление скрытого поля помогло мне решить проблему.