[ 
http://issues.apache.org/struts/browse/SHALE-287?page=comments#action_38618 ] 
            
Mike Meessen commented on SHALE-287:
------------------------------------

Hi Craig,

I just spent a day of work trying to understand, reproduce and find a patch for 
the described issue. 

At first a "management summary", details follow.

If the user supplied an invalid token as consequence of for example using the 
back button, we have to remove the token attribute to avoid being stuck with 
the old (invalid) token forever.

Details:

* The fact that myfaces prior to v1.1.2 behaves differently then v1.1.2 and 
above seems to be a very little bug in the old myfaces implementation 
concerning UIInput validation. As a conclusion, I focused on shale and the 
token tag, trying to achive the behavior I experienced with myfaces 1.1.1.

* In my opinion, two phenomenes appear at the same time here:
1) In certain cases, the token value should be regenerated to avoid the 
application to get stuck.
2) In cases where the token detects that the submission it gets has not been 
initiated from the last served viewId (thus, the user clicked the back button 
once or more), we'd need a mechanism to redirect to the last served viewId, 
providing a fresh representation of that viewId.

At first, I tried to fix point 1.

The token tag operates as standard UIComponent with standard jsf component 
validation to "manipulate" faces behavior. If a valid token gets submitted, the 
application phases go through as normal:

* restoreView
* applyRequestValues
* processValidations    <= That's where the token tests it's validity
* updateModelValues
* invokeApplication
==> renderResponse

But, what if the submitted token value is invalid? It would look like this:

* restoreView
* applyRequestValues
* processValidations    <= That's where the token tests it's validity
==> renderResponse

Taking things a bit further, I noticed that since the "Apply Request Values" 
phase already wrote the new (invalid) token value to the token UIComponent, 
this (invalid) value will be used for rendering the response... So as a 
conclusion, the response will be generated with the submitted (invalid) token 
value.

To avoid this, I simply reset the token value (I removed the 
TOKEN_ATTRIBUTE_KEY from the UIComponent's attributes map) if the validation 
fails. Then, in the render response phase, the token tests it's value and 
generates a new one.

The result is that I:
* successfully told JSF that a validation error occured, so I bypassed any 
model updates and application invokes (the primary goal of the token component)
* delivered a fresh page to the user, displaying the latest valid state of the 
viewId
* generated a new token, so the user will be able to go on from the served page.

The only inconvenience I see applying this method is the following:
-------------------------------------------------------------------------------------------
When a token is generated, it is put in a map in session scope called 
"ShaleConstants.TOKENS".
When a valid token is submitted, the TokenProcessor.verify() method removes it 
from that map. This is the right mechanism, since this token has now been 
consumed and should never be consumed again.
BUT: in my case, where a token is re-generated due to an invalid request, the 
old token (which would have been submitted by a valid request) will stay in the 
"ShaleConstants.TOKENS" map in the session scope. With the current 
architecture, I think I have no chance to know what would have been the correct 
token in order to remove it from that map.
I have been unable to find a *simple* way around that without having to change 
this mechanism...

I included a patchfile for shale(-core) which applies my one-line patch...
------------

As I mentioned before, this only solves the first phenomene...

To solve the second one (which would be "serve the right viewId even if an old 
page gets submitted"), I think the only simple way would be:
* shale must keep in mind which was the last served viewId (page)
* whenever a HTTP POST request comes from another viewId as the one the user 
was supposed to have in front of him, the last served viewId is re-served (with 
a re-generated token value). That would be achieved by a redirect in the 
validation phase of the token... I know this is not really pretty but I think 
it would solve any double-submit, back-button, etc. problems we all are 
struggling with.

-----------

I hope this has been well described, it really isn't easy ;-)

Looking forward to hearing from you!!

Regards,
Mike Meessen

> Faulty behavior of the "token" component with Apache MyFaces >1.1.1
> -------------------------------------------------------------------
>
>                 Key: SHALE-287
>                 URL: http://issues.apache.org/struts/browse/SHALE-287
>             Project: Shale
>          Issue Type: Bug
>          Components: Core
>         Environment: OS: Microsoft Windows XP SP2
> Servlet Container: jakarta-tomcat-5.5.9
>            Reporter: Mike Meessen
>         Assigned To: Craig McClanahan
>         Attachments: shale-test-core.war, ShaleIssueDemo.war, 
> ShaleIssueDemo.zip, Token.java.diff
>
>
> This issue appears when using Apache MyFaces as of version 1.1.2. The MyFaces 
> project states the following about their 1.1.2 release:
> [Quote]
> This is the first official release of what we are now calling the "core." The 
> core refers to the JSF 1.1 implementation as specified by JSR-127. It has 
> passed Sun's TCK and is considered to be 100% compliant with the spec.
> [/Quote]
> So as a conclusion, I think everyone who's still using MyFaces 1.1.1 should 
> hurry upgrading his code to be 1.1.2 compliant.
> Allthough Shale should be JSF-implementation-independant, it seems this issue 
> appears or not depending on the used MyFaces version.
> Steps to reproduce the issue:
> * Use a simple JSF submission form to which you add Shale's Token tag to 
> check for illegal form resubmissions.
> * As long as you submit the form correctly, everyting works fine.
> * Press F5 (page refresh) once, the browser warns about HTTP POST data 
> resubmission.
> * Discard the warning and go on resending the same HTTP request.
> * Shale recognizes the resubmission and acts correctly (no application logic 
> gets invoked).
> **** This is the part where the behavior changes according to what MyFaces 
> version is used:
> With MyFaces 1.1.1
> --------------------------
> * Resubmit the form correctly (using the submit button).
> ==> The workflow goes on and the form is correctly submitted.
> With MyFaces 1.1.2 and above
> -----------------------------------------
> * Resubmit the form correctly (using the submit button).
> ==> Nothing happens. No new token is generated, so no application logic gets 
> invoked and the workflow stucks.
> I attached a sample project which demoes the issue.
> -- EDIT: 
> I forgot to mention that with both MyFaces versions, I set the context-param 
> "org.apache.myfaces.ALLOW_JAVASCRIPT" to false. In theory, this shouldn't 
> make a difference since I'm using HTTP POST just as the javascript would do, 
> but I think it's worth the hint.
> Regards,
> Mike

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
http://issues.apache.org/struts/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Reply via email to