tapestry-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Inge Solvoll" <inge.tapes...@gmail.com>
Subject Re: "Token" approach to avoiding double submits
Date Tue, 07 Mar 2006 10:41:28 GMT
I found a working solution for myself now, that involves the least possible
amount of coding for each page. Now I only have to include my Token
component at the beginning of each form. So far it's working, please tell me
if anyone sees why this shouldn't work.

Here's my solution, I really think tapestry should have some kind of native
support for this...

PAGE-file

        <property name="tokenServer" persist="session"/>
        <property name="tokenClient"/>

    <component id="token" type="Hidden">
        <binding name="value" value="tokenClient"/>
    </component>

HTML-file

<input type="hidden" jwcid="token"/>

JAVA-file

  public void pageBeginRender(PageEvent event) {
    log.debug("Entered pageBeginRender");
    if (!getRequestCycle().isRewinding()) {
      String newToken = generateToken();
      setTokenServer(newToken);
      setTokenClient(newToken);
    }
  }

  protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
{
    super.renderComponent(writer, cycle);
    log.debug("Entered renderComponent");
    if (getRequestCycle().isRewinding()) {
      String tokenClient = getTokenClient();
      String tokenServer = getTokenServer();
      log.debug("Token from form: " + tokenClient);
      log.debug("Token on server: " + tokenServer);

      if (tokenClient == null || !tokenClient.equals(tokenServer)) {
        log.error("Token for page is not valid, redirect to obtain last good
state");
        throw new PageRedirectException(this.getPage());
      }
    }
  }



On 3/3/06, Nick Westgate <nick@key-planning.co.jp> wrote:
>
> Off the top of my head, I suppose you could put the token in the
> page base class. But then to make it unique you'd have to include
> something (for example the page name) in the token string.
>
> That should work, but perhaps there's a better way in T4.
> Hopefully I'll find out in my next project. ;-)
>
> Cheers,
> Nick.
>
>
> Inge Solvoll wrote:
> > Looks like a good solution!
> >
> > The problem for the future is that getVisit() is deprecated, so from 4.1we
> > have to inject the visit object as state into all pages if we want to
> use
> > this pattern. That qualifies as "unnecessary plumbing" for me, the
> > expression used in the tapestry commercials :)
> >
> > Maybe my code should use the visit object in every page anyway, I don't
> use
> > any ASOs yet, partly because our application has been ported from
> struts,
> > and is still partly struts-implemented, needing quite a few integration
> > points.
> >
> > Inge
> >
> > On 3/3/06, Nick Westgate <nick@key-planning.co.jp> wrote:
> >
> >>Hi Inge.
> >>
> >>I use the FlowSynchronizer pattern that Sohail linked to,
> >>and here's how I avoid code duplication.
> >>
> >>In my T3 apps the FlowSyncronizer is stored in the Visit object.
> >>My border component includes the token in every page:
> >><input jwcid="@Hidden" value="ognl:page.visit.flowSynchronizer.token"/>
> >>
> >>In addition, I didn't like the exceptions, so instead:
> >>     private boolean resubmit;
> >>     public void setToken(String token)
> >>     {
> >>         // first compare the token
> >>         if (this.token == null || !this.token.equals(token))
> >>         {
> >>             resubmit = true;
> >>         }
> >>         else
> >>         {
> >>             // reset token on match -> subsequent duplicate submission
> >>will fail
> >>             this.token = null;
> >>             resubmit = false;
> >>         }
> >>     }
> >>
> >>My BasePage class has:
> >>     public boolean isResubmit()
> >>     {
> >>         // check if this cycle is a resubmit (before doing inserts etc)
> >>         Visit visit = (Visit)getVisit();
> >>         return visit.flowSynchronizer.isResubmit();
> >>     }
> >>
> >>Then in any page where you need to know, just call isResubmit().
> >>
> >>Cheers,
> >>Nick.
> >>
> >>
> >>Inge Solvoll wrote:
> >>
> >>>This is one of the cases where it would be really really sweet to be
> >>
> >>able to
> >>
> >>>extend components, including specifications...
> >>>
> >>>On 3/2/06, Geoff Longman <glongman@gmail.com> wrote:
> >>>
> >>>
> >>>>You could craft your own Form component that handles the hidden and
> >>>>use the tapestry-flash thingy to save the token
> >>>>
> >>>>Geoff
> >>>>
> >>>>On 3/2/06, Inge Solvoll <inge.tapestry@gmail.com> wrote:
> >>>>
> >>>>
> >>>>>I've tried to copy the token-approach from struts into Tapestry,
to
> >>>>
> >>>>avoid
> >>>>
> >>>>
> >>>>>crashes when the user hits the "refresh"-button in the browser. Using
> >>>>
> >>>>this
> >>>>
> >>>>
> >>>>>approach, the html rendered can only be submitted once. My problem
is
> >>>>
> >>>>that
> >>>>
> >>>>
> >>>>>the code I've written so far requires too much code copying and
> >>>>
> >>>>repeating,
> >>>>
> >>>>
> >>>>>and I was wondering if someone has ideas on how to make the
> >>>>
> >>>>implementation a
> >>>>
> >>>>
> >>>>>bit less intrusive for my pages.
> >>>>>
> >>>>>I could include this code in my base class that all my page classes
> >>>>
> >>>>inherit
> >>>>
> >>>>
> >>>>>from, but then I would have to inject WebRequest into every single
> page
> >>>>
> >>>>in
> >>>>
> >>>>
> >>>>>my application, and that's not the tapestry way to do page design,
is
> >>>>
> >>>>it?
> >>>>
> >>>>
> >>>>>I'm pretty sure that this is functionality that I need in all my
> pages
> >>>>>(refresh of a post causes crash most of the times in my tapestry
> code).
> >>>>>Maybe this can be done with a servlet filter, or better, with a
> >>
> >>HiveMind
> >>
> >>>>>service that intercepts the request?
> >>>>>
> >>>>>Here's my code so far:
> >>>>>
> >>>>>public void pageBeginRender(PageEvent event) {
> >>>>>   if (getRequestCycle().isRewinding()) {
> >>>>>     String token = getRequest().getParameter("token");
> >>>>>     if (token == null || !token.equals(getToken())) {
> >>>>>       log.error("Token for page is not valid, redirect to obtain
> last
> >>>>
> >>>>good
> >>>>
> >>>>
> >>>>>state");
> >>>>>       throw new PageRedirectException(this);
> >>>>>     }
> >>>>>   }
> >>>>>   else {
> >>>>>     setToken(generateToken());
> >>>>>   }
> >>>>>
> >>>>>}
> >>>>>
> >>>>>.html:
> >>>>><input jwcid="@Any" type="hidden" name="token" value="ognl:token"/>
> >>>>>
> >>>>>.page:
> >>>>><property name="token" persist="session"/>
> >>>>>
> >>>>>
> >>>>>An article on the subject:
> >>>>>http://www.javalobby.org/java/forums/m91956568.html
> >>>>>
> >>>>>
> >>>>
> >>>>
> >>>>--
> >>>>The Spindle guy.          http://spindle.sf.net
> >>>>Get help with Spindle:
> >>>>http://lists.sourceforge.net/mailman/listinfo/spindle-user
> >>>>Blog:                     http://jroller.com/page/glongman
> >>>>Feature Updates:          http://spindle.sf.net/updates
> >>>>
> >>>>---------------------------------------------------------------------
> >>>>To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> >>>>For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
> >>>>
> >>>>
> >>>
> >>>
> >>---------------------------------------------------------------------
> >>To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> >>For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
> >>
> >>
> >
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
>
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message