3

During upgrade from Tomcat 7.0.50 to Tomcat 8.5.15 it stopped recognizing one of the POST parameters of one of my methods: what I get instead of the normal response is this message

HTTP Status [400] – [Bad Request]

Type Status Report

Message Required String parameter 'password' is not present

Description The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).

Apache Tomcat/8.5.15

The method signature is:

@RequestMapping(value = "/login", method = RequestMethod.POST)
@ResponseBody
public Map<String, Object> login(
    @RequestParam("password") String passwordHash,
    @RequestParam("username") String loginName,
    @RequestParam(value = "clientId", required = false) String clientId,
    HttpServletRequest request,
    HttpServletResponse response)
    throws NoSuchAlgorithmException {//...

I've captured traffic from the request and, as you can see, the password POST parameter is contained in POST x-www-form-urlencoded parameters:

POST http://<masked>/Server/user/login HTTP/1.1
Host: <masked>
Connection: keep-alive
Content-Length: 270
Origin: http://<masked>
X-Requested-With: ShockwaveFlash/26.0.0.131
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.104 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: */*
Referer: http://<masked>
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,ru;q=0.6,he;q=0.4
Cookie: <masked>

noremember=true&password=C9TUq%2BYMIbeoW%2ByfoSCt9QJoOnmSGR8BqRKdOjufjE7%2FoHUDpPf3FHSvCUbZu4EBSKkJV2ryGs1Q77D7SFbBKZZ3joWcMTN6aTsgmPsOdW0Md1qcOkB4w4L3F53XZRlKUp2RaxCjoE0AIr%2B0WLomGFSrn8u8iTf2p4Z7Mo6ZKPA%3D&username=test%40example%2Ecom&clientId=1858390758%2E1481631908

The strange this is that it worked perfectly under Tomcat 7

How can this be helped?

Community
  • 1
  • 1
Dmitry Ginzburg
  • 7,391
  • 2
  • 37
  • 48
  • Did you check that only the password is not found? Can you check by testing the other parameters first that you're still receiving `@RequestParam("username")`? – Turtle Jun 21 '17 at 08:09
  • @Nathan Well, I've tried running `curl --data 'password=C9TUq%2BYMIbeoW%2ByfoSCt9QJoOnmSGR8BqRKdOjufjE7%2FoHUDpPf3FHSvCUbZu4EBSKkJV2ryGs1Q77D7SFbBKZZ3joWcMTN6aTsgmPsOdW0Md1qcOkB4w4L3F53XZRlKUp2RaxCjoE0AIr%2B0WLomGFSrn8u8iTf2p4Z7Mo6ZKPA%3D&clientId=1858390758%2E1481631908' http:///Server/user/login` (without `username` parameter), but the error remains: `Required String parameter 'password' is not present` – Dmitry Ginzburg Jun 21 '17 at 08:12
  • I believe the error don't just comes from `password` missing. It's just that the first parameter mapped with `@RequestMapping` is `password`. What I was proposing was to place the `@RequestMapping("username")` before the one with password for example. If the error becomes `Required String parameter 'username' is not present`, then you will know that no parameters are parsed. – Turtle Jun 21 '17 at 08:26
  • @Nathan (it's easier for me now not to touch the existing code) I have another GET/POST method `isLoginNameAvailable` with the only required parameter `loginName`, which is NOT getting parsed when being sent in the POST request, but IS parsed when I'm sending it with GET parameters. I can conclude that POST parameters are not processed at all, while GET ones are – Dmitry Ginzburg Jun 21 '17 at 08:28
  • With POST method, you should use `@RequestBody` instead of `@RequestParam`. – Cà phê đen Jun 21 '17 at 08:32
  • @Càphêđen No, I shouldn't. see https://stackoverflow.com/questions/28039709/what-is-difference-between-requestbody-and-requestparam – Dmitry Ginzburg Jun 21 '17 at 08:37
  • Can you `curl -X POST http:///Server/ -d loginName=` on your `isLoginNameAvailable` endpoint? this way you'll be sure that you're not parsing those post parameters. – Turtle Jun 21 '17 at 08:49
  • @Nathan https://gist.github.com/ginz/9d16659ba2c078fc8a5caeb6ddb06525 – Dmitry Ginzburg Jun 21 '17 at 09:07
  • @DmitryGinzburg Okay. I'll delete my comments then, as they were just a misunderstanding. And sorry, but I **cannot** access personnal storage sites. – Turtle Jun 21 '17 at 09:07
  • `$ curl -XPOST http:///Server/user/isLoginNameAvailable -d loginName=xxx $ curl -XPOST http:///Server/user/isLoginNameAvailable -d loginName=xxx {"result":"OK","response":true}` – Dmitry Ginzburg Jun 21 '17 at 09:13

1 Answers1

1

Finally the reason was found. I've had maxPostSize="0"parameter in server.xml's Connector in my old configuration of Tomcat 7.0.50 and I've copied it to the new configuration, but since Tomcat version 7.0.63 maxPostSize="0" doesn't mean unlimited, but "empty", so maxPostSize="-1" should be used

The meaning of the value zero for the maxPostSize has also been changed to mean a limit of zero rather than no limit to align it with maxSavePostSize and to be more intuitive. (markt)

Tomcat 7.0.63 changelog

Dmitry Ginzburg
  • 7,391
  • 2
  • 37
  • 48