Restrict Spring page view into POST only

1.5k views Asked by At

My Spring controller looks like this:

@Controller
@RequestMapping(value = "calc")
public class CalcController {

  protected final Log logger = LogFactory.getLog(getClass());

  @Autowired
  private MyService myService;

  @RequestMapping(method = RequestMethod.GET)
  public String showCalcPage(
      @ModelAttribute("myModel") MyModel myModel,
      Model model, HttpServletRequest request) {

      // assemble page

    return "calc";
  }

  @RequestMapping(method = RequestMethod.POST)
  public String showResultsPage(
      @ModelAttribute("myModel") MyModel myModel,
      BindingResult result, Model model,
      final RedirectAttributes redirectAttributes,
      HttpServletRequest request) {

    myService.evaluate(myModel);

    redirectAttributes.addFlashAttribute("myModel", myModel);
    model.addAttribute("myModel", myModel);

    return "redirect:calc/results";
  }

  @RequestMapping(value = "/results")
  public String showResultsPage(ModelMap model,
      @ModelAttribute("myModel") final MyModel myModel,
      final BindingResult bindingResult) {

    // assemble page

    return "results";
  }
}

I have a mapping of the URL calc with both GET and POST and another for calc/results.

This works perfectly for me but whenever I try to access calc/results directly, the page still renders.

Hence I did a POST restriction to its RequestMethod like:

  @RequestMapping(value = "/results", method = RequestMethod.POST)
  public String showResultsPage(ModelMap model,
      @ModelAttribute("myModel") final MyModel myModel,
      final BindingResult bindingResult) {

    // assemble page

    return "results";
  }

This eliminated the direct viewing of the mapping by throwing a 405 but when I submit my form from calc, the error still persists.

How do I merge these two situations that I have?

I actually just want two controllers like the one below to implement POST and page restriction but it's not working in my part (I diagnosed it to the different mapping of jsp).

@Controller
@RequestMapping(value = "calc")
public class CalcController {

  protected final Log logger = LogFactory.getLog(getClass());

  @Autowired
  private MyService myService;

  @RequestMapping(method = RequestMethod.GET)
  public String showCalcPage(
      @ModelAttribute("myModel") MyModel myModel,
      Model model, HttpServletRequest request) {

      // assemble page

    return "calc";
  }

  @RequestMapping(value = "/results", method = RequestMethod.POST)
  public String showResultsPage(
      @ModelAttribute("myModel") MyModel myModel,
      BindingResult result, Model model,
      final RedirectAttributes redirectAttributes,
      HttpServletRequest request) {

    // assemble page    

    myService.evaluate(myModel);
    model.addAttribute("myModel", myModel);

    return "redirect:results";
  }
}
1

There are 1 answers

2
AudioBubble On BEST ANSWER

I finally implemented both POST restriction and successful viewing of the calc/results page (but without redirect since it causes a "redirect loop" according to my Tomcat server).

Here is the final controller:

@Controller
public class CalcController {

  protected final Log logger = LogFactory.getLog(getClass());

  @Autowired
  private MyService myService;

  @RequestMapping(value = "calc", method = RequestMethod.GET)
  public String showCalcPage(
      @ModelAttribute("myModel") MyModel myModel,
      Model model, HttpServletRequest request) {

    // assemble page

    return "calc";
  }

  @RequestMapping(value = "calc/results")
  public String showResultsPage(
      @ModelAttribute("myModel") MyModel myModel,
      ModelMap model, final BindingResult bindingResult,
      HttpServletRequest request) {

    // assemble page

    // apply BindingResult validation in da fyoochoor
    myService.evaluate(myModel);
    model.addAttribute("myModel", myModel);

    return "results";
  }
}

Visiting calc/results directly now throws an HTTP 500 and that will keep it secured. Just make sure to declare a page for this exception in your web.xml for aesthetics upon deployment.