开发者

Unwanted comma-separated arguments to Spring controller method

I'm seeing a strange problem with a Spring MVC controller. This method is intended to set the password. It takes two form parameters "password" and "confirmPassword". The first time the form is called, this works fine-- the fields are passed to the method.

The problem occurs when the form is submitted a second time. If the form is incorrectly filled out the first time, the user is correctly sent back to the form page and prompted to enter the password again. However the arguments to the method are incorrect on the second try. The arguments are a comma separated list which includes the first form entry concatenated with the second.

Example:

First form post with field "password" has a value of "abc". Method argument "password" has value "abc".

Second form post with field "password" and a value of "xyz". Method argument "password" has value "xyz,abc".

The Spring MVC docs don't indicate much useful. Somehow the old form post is remembered and included. Anyone have experience in solving this?

Controller method is below:

@RequestMapping(value = "/account/reset", method = RequestMethod.POST)
public String resetPassword(@RequestParam("password") String password,
        @RequestParam("confirmPassword") String confirmPassword,
        @RequestParam("hash") 开发者_如何学CString 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. Several responders have suggested that perhaps the problematic posts have extra URL parameters or hidden form fields resulting in duplicate field names. I confirmed with Fiddler that this is not the case. Here's the raw request from the third try. (slightly edited to remove session 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


I think the reason for this is because of

return "redirect:/session/signin?passwordReset=true";

With redirect: the framework uses the url-rewriting technique, similar to the basic response.sendRedirect(...) in servlets, and hence the parameter,values are appended along with the request to the next consequent requests and so on.

Try using a different mechanism rather than "redirect:"


So after more than a year I figured this out.

The problem was a custom interceptor that stored the request cache on each request. I do this so that when a user logs on, he will go back to the previous screen. But it's completely inappropriate for a "reset password" screen.

The mechanism was that when request.getParameter(Name) is called the SavedRequestCacheWrapper would then concatenate the actual HTTP request parameters with the stored parameters from that last request.

The solution is to (a) have this interceptor ignore the reset password screen and (b) ignore all post requests to prevent this kind of request parameter value concatenation.

To the other responders, thanks for all the good ideas. (And to the anonymous user who put a bounty on this - thanks for causing me to go back and take another look.)


If you post a third time, does the list grow to three, too? This would indicate that the problem is related to the user's session. Or, if the list stays at two, then the problem is in the request. I'm guessing that the list grows to three, since the info you posted from Fiddler shows no sign of duplication in the request.

To confirm the data is in the session, check its contents (ex. print to a log, use a debugger, print to the web page in a dev environment) for data under the same keys -- "password", "hash", etc.

Also, see this other response about why data might be in the user's session, ex. you used the @SessionAttributes annotation somewhere.


You will get comma seperated values when you have multiple form fields that have the same name. A common cause for this is to have hidden inputs and text inputs with the same name. The first time the page posts, the hidden inputs will be empty so, no commas. The second (and subsiquent) time the page posts, the hidden inputs will have values, so you get commas.


It looks like the old values somehow appear as GET parameters, i.e. either you have <form action = ".../account/reset?password=abc"> in the second form, or action is empty and URL of the second form itself is .../account/reset?password=abc. Though I can't find anything responsible for it in your code.


Are you somehow specify the form fields a second time when you come back from the validation step? Use Firebug or something similar to inspect what you're sending and/or post your jsp (or similar) page.


Looks like this might be caused by the issue https://jira.springsource.org/browse/SEC-1258 "SavedRequestAwareWrapper causes trouble in 3.0 M2 in combination with Spring MVC"


In my case, I had associated hidden field with a path that was unused. Removing the hidden field helped me resolve the issue.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜