5

I have several SprigMVC methods like this below, returning either a ModelAndView or a Responsebody. When users makes a request to these urls missing the required parameters they naturally get the message "Required String parameter 'id' is not present".

From security perspective I want to hide this detailed description messages from users. So a hacker don't easily know the missing parameters and will get a 400 error without any description. Is this possible via a spring configuration/Spring Security or I have to manually refactor all my methods to return a custom message somehow.

@RequestMapping(value = "/payment", method = RequestMethod.GET)
public ModelAndView getReponse(@RequestParam(value = "id", required = true)) {

    return model;
}

@RequestMapping(value = "/status", method = RequestMethod.GET)
public @ResponseBody String getStatus(@RequestParam(value = "id", required = true) String id) {

    return "string";
}
Spring
  • 11,333
  • 29
  • 116
  • 185
  • So bypassing that error will also help right? – Rahman Oct 28 '15 at 08:52
  • @Rehman not sure what you mean by bypass but probably – Spring Oct 28 '15 at 08:56
  • Now its clear after editing your question. I was thinking about `required=false`. But you want 400 – Rahman Oct 28 '15 at 08:57
  • 1
    can you show your `web.xml`? particularly the `error-page` part, if you have it configured (some examples here http://stackoverflow.com/questions/7066192/how-to-specify-the-default-error-page-in-web-xml) – Michal M Oct 28 '15 at 09:02
  • 1
    You can use @ExceptionHandler. Here is a an example how to use it http://stackoverflow.com/questions/13356549/handle-error-404-with-spring-controller – pokemzok Oct 28 '15 at 09:03
  • @Michal M tnx looks like web.xml solution works. I have to see what is the best approach – Spring Oct 28 '15 at 09:22

2 Answers2

9

What you actually need is a global handler for MissingServletRequestParameterException, which is thrown by Spring when a request parameter is missing. The easiest way to tackle this problem is to use ControllerAdvice that will handle it for all your controllers.

import org.springframework.web.bind.MissingServletRequestParameterException;

@ControllerAdvice
class MissingServletRequestParameterExceptionHandler {
    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public String handleMissingParameter() {
        return "Your custom result";
    }
}

If you want to hide the missing parameter message only for a particular controller, just move handleMissingParameter method to this controller without creating the ControllerAdvice.

Daniel Olszewski
  • 13,995
  • 6
  • 58
  • 65
  • tnx. does this approach has any advantage over using in my web.xml? I just tried and I could show my own custom error page for all 400 errors – Spring Oct 28 '15 at 09:21
  • If you just want to display a simple error page then no, is sufficient. But you can use this handler to log such a situation and since you wrote about attacks that information may be interesting for you. – Daniel Olszewski Oct 28 '15 at 09:26
  • yes indeed for logging! tnx but its not clear how can I use it for a single controller method? And is there a way to get the HttpRequest object for detailed logging – Spring Oct 28 '15 at 09:31
  • 1
    `@ExceptionHandler` works on the class level. If you put it inside a controller class, it handles specified exception for all methods inside this class. Unfortunately, it's not possible to choose only a selected method. You need some custom solution, e.g., pass a request to the handler method and verify whether for that URL you should execute the handler or re-throw the exception. – Daniel Olszewski Oct 28 '15 at 09:51
4

I personally upvoted Daniel Olszewski's answer because it's hip, nice, concise and readable, although in a customer-facing, publicly available site (when you go beyond the fast prototyping with Spring Boot phase and need to be perfectly sure that nothing gets through) one may want to use it together with the plain-old error-page in web.xml approach (some examples here: Handle error 404 with Spring controller).

It may not be fun (I, personally, despise anything XML related beyond explainability), but (unless you're not using web.xml at all in favor of WebApplicationInitializer), web.xml is almost the lowest layer in a web app and no error page (no matter the exception or URL mapping) will get through it, just remember to map all the HTTP status codes (i.e. have one default error-page element without the child error-code element).

The solution for WebApplicationInitializer is analogous, some xamples here: Using Spring MVC 3.1+ WebApplicationInitializer to programmatically configure session-config and error-page.

The lowest layer approach would be to set the error page contener-wide, e.g. for Tomcat: http://linux-sxs.org/internet_serving/c581.html.

Community
  • 1
  • 1
Michal M
  • 1,521
  • 14
  • 35