Announcement Announcement Module
Collapse
No announcement yet.
AbstractWizardFormController and GET parameter binding Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • AbstractWizardFormController and GET parameter binding

    I use an AbstractWizardFormController to add price changes to a product. The URL addPriceChange.html is mapped to the controller, and I use a query string (aka "GET") parameter (id=X) to tell the formBackingObject() method what product it should get from the database.

    addPriceChange.html?id=1 will start the process of adding a price change to product number 1, etc.

    The first page view (i.e. index 0 of the setPages() string array) renders a HTML form with a _target1 parameter in order to send the process to its next stage:

    <form method="post">
    ...
    <input type="text" name="${status.expression}" value="${status.value}">
    ...
    <input type="submit" name="_target1">
    ...
    </form>

    The form is processed, and all the POSTed <input> fields are bound to the form backing object. So far, so good.

    The "problem" is that it seems that the initial id=X GET parameter is also bound to the form backing object, even though I only intended it to be used to initialize the form backing object.

    (This happens as the above mentioned <form>, lacking an action="..." attribute, is POSTed to itself, and thus the id=X is still present in the query string part of the URL.)

    It took me quite a while to realize that the initial id=X GET parameter in turn was causing a setId() call on the form backing object - and it caused quite a lot of trouble today. I simply didn't realize that query string "GET parameters" was bound in the same way as regular POST parameters in such cases - probably because the progress of an AbstractWizardFormController is otherwise tied to POSTs.

    The workaround is obviously to change the <form> in the first (index 0) view to this:
    <form method="post" action="addPriceChange.html">

    ...because then the id=X parameter will not be present in subsequent POSTs.

    But my question is: Should it work this way in the first place? Perhaps it really is obvious to most people that query string parameters will be bound in the same way as regular form <input> parameters, but I didn't think of it during the first hour of debugging. :oops:

  • #2
    Yep, it should Basically your browser will convert all inputs into name=value type strings and either prepend them onto the GET, or set them in the POST section depending on your action method.

    If you are posting to a url which contains parameters, then yes these parameters will also be bound.

    As an aside, rather than dealing with "id=1", you could write a propertyEditor which converts that "id" into an actual object. Bit nicer than doing the object lookup in your controller. If you are already doing this, apologies

    Comment


    • #3
      Thanks for the answer. I guess I'm just dumb, then.

      Originally posted by yatesco
      As an aside, rather than dealing with "id=1", you could write a propertyEditor which converts that "id" into an actual object. Bit nicer than doing the object lookup in your controller. If you are already doing this, apologies
      But the query string parameter, id=1, isn't a property that should be bound to a command object. It's just there to initialize the command object. It is ONLY used in the formBackingObject() method, like this:

      Code:
      protected Object formBackingObject&#40;HttpServletRequest req&#41; throws ServletException &#123;
          String id = req.getParameter&#40;"id"&#41;;
          Product prod = mgr.getProduct&#40;id&#41;;
          ...
      &#125;
      ...where mgr is the product manager (service class).

      Are you telling me this could be handled with property editors? If so, I'm very interested in how!

      Comment


      • #4
        No, a propertyEditor would only make sense if it was bound to your command object

        Comment


        • #5
          Originally posted by yatesco
          Yep, it should Basically your browser will convert all inputs into name=value type strings and either prepend them onto the GET, or set them in the POST section depending on your action method.
          This got me thinking... Seeing as Spring MVC encourages you to bind to business model objects (instead of separate form-backing objects, like Struts), it means you're technically enabling any user who can edit one property of your business object to edit all properties of your business object.

          If I, for example, have a User object, that a user can edit (edit their own name, contact info, etc.), and the User class has an "internal comment" property only intended for administrators as well, all the user has to do to overwrite this property is to insert a comment=whatever in his POST request (f.ex. using a HTTP seaders interceptor/proxy/editor program).

          Of course he has to know/guess what properties to insert, but I can think of lots of more sensitive properties than a comment.

          I guess this is where Acegi Security and MethodInvoker security enters the picture?

          Comment


          • #6
            Could point

            Comment


            • #7
              OK, it *really* got me thinking You can prevent this by setting the "allowedFields" property on http://static.springframework.org/spring/docs/1.2.x/api/org/springframework/validation/DataBinder.html#setAllowedFields(java.lang.String[])

              Comment


              • #8
                Ah, thanks. Very nice to know, indeed. Perhaps this should be highlighted in the tutorials as well? Ah well, I guess security never was a high priority in tutorials anyway.

                Comment

                Working...
                X