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 Fri, 10 Mar 2006 13:37:59 GMT
I was thinking more in terms of using ajax for letting the user know about
the invalid page he is on before he submits the form. Don't know if this is
useful in any way.

My token system works great so far, can't really see any problems with
direct links, but I'm not using it for ajax...

One major improvement would be, as Geoffs suggested, to extend the Form
component to optionally include a token. This way I could skip the token
part in all my pages:

<form jwcid="@Form">
<!--
<span jwcid="@Token"/>
-->

Inge

On 3/8/06, Mark Stang <mstang@pingidentity.com> wrote:
>
> Inge,
> That sounds like an interesting idea.  There is interest here in Tacos and
> AJAX, but we haven't started using it yet.  In my case, I have a single page
> with a component that "swaps" out other components, so I will be trying your
> solution at a component level.
>
> The one issue we had when we tried something similar to this was with
> direct-links, have you done any testing yet?
>
> Thanks for the info!
>
> regards,
>
> Mark
>
>
> -----Original Message-----
> From: Inge Solvoll [mailto:inge.tapestry@gmail.com]
> Sent: Wed 3/8/2006 1:07 AM
> To: Tapestry users
> Subject: Re: "Token" approach to avoiding double submits
>
> I had to do another fix, reset the server token to null in pageEndRender
> of
> the component, because the page containing the token may not be rendered
> after rewind. It seems to work well now.
>
> In combination with the tacos feature of intercepting back and forward
> button events, this  solution actually should be sufficient. It might also
> be interesting to explore how the token-solution could be used with
> AJAX-calls to the server without submits, to check if the page has a valid
> ticket.
>
> Inge
>
> On 3/7/06, Mark Stang <mstang@pingidentity.com> wrote:
> >
> > Inge,
> > Thanks for posting it, I will give it a shot!
> >
> > regards,
> >
> > Mark
> >
> >
> > -----Original Message-----
> > From: Inge Solvoll [mailto:inge.tapestry@gmail.com]
> > Sent: Tue 3/7/2006 3:42 AM
> > To: Tapestry users
> > Subject: Re: "Token" approach to avoiding double submits
> >
> > Of course, I meant JWC-file where it says PAGE-file. The code listed is
> > for
> > a Token-component.
> >
> > On 3/7/06, Inge Solvoll <inge.tapestry@gmail.com> wrote:
> > >
> > > 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.1 we
> > > > > 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