Apache-Shiro: User authenticates within AJAX, how to restore GET-Variables after login? - ajax

in my JavaEE-Application, I am using Apache Shiro[1] for user-authentication.
My users are navigating via GET-URLs, as for example "/company/index.xhtml?companyId=327".
I have enabled programmatic login, following a guide[2] from BalusC:
SavedRequest savedRequest = WebUtils.getAndClearSavedRequest(Faces.getRequest());
My problem is, that savedRequest.getRequestUrl() does not contain the previous mentioned GET-parameteres, when my case is asynchronous POST with or without RememberMe; just "/company/index.xhtml" is returned, for example. It seems as if "FacesAjaxAwareUserFilter" (see [2]) is not GET-params aware. Everything works fine on synchronous GET-calls.
How do I get the GET-parameters after an shiro-redirect because of authentication-needed in case of using "FacesAjaxAwareUserFilter"?
[1] https://shiro.apache.org/
[2] Followed this great article about JavaEE and Shiro: http://balusc.blogspot.de/2013/01/apache-shiro-is-it-ready-for-java-ee-6.html

JSF ajax requests are sent to the URL as generated by <h:form>. This is however by default not exactly the current URL including the query string, it's by default the current URI without the query string.
There are several ways to fix this. The simplest but ugliest way is to use JS:
<h:form id="foo">
...
</h:form>
<script>document.getElementById("foo").action += "?" + location.search;</script>
The cleanest way would be to create a custom ViewHandler whose getActionURL() (as used by <h:form>) will return the desired URL with the query string.
JSF utility library OmniFaces has already such a component which does that based on view parameters: the <o:form> which basically extends the <h:form> with support for includeViewParams="true" (exactly the same way as <h:link> does).
<f:metadata>
<f:viewParam name="companyId" value="#{bean.company}" />
</f:metadata>
...
<o:form includeViewParams="true">
...
</o:form>

Related

OmniFaces validateOrder disabling

I'm trying to use validateOrder component to validate two java.util.Date objects. It is similar to showcase example on this link (PrimeFaces example). Everything works perfect, but i have one question:
What if 2nd date field is not required?
In that case i'm getting nullpointer exception, and since validateOrder has "disabled" attribute, i was wondering is it worth/possible enabling/disabling it via ajax every time the 2nd date is inserted/removed. If not, i guess i'll stick to Balus' approach for JSF2.0 cross-field validation that you can read about on this link.
Let the disabled attribute check if the 2nd field is filled in. If it's not filled in, the request parameter value associated with field's client ID will be empty. Use exaclty that to let disabled attribute evaluate to true.
<p:calendar ... binding="#{endDate}" />
...
<o:validateOrder ... disabled="#{empty param[endDate.clientId]}" />
Code is as-is. No additional backing bean property necessary for binding.
See also:
How does the 'binding' attribute work in JSF? When and how should it be used?

jsf execution order of f:events

What is the execution order of those?
Here is a question about possible f:event event names: List of JSF 2 events?
preRenderComponent
preRenderView
postAddToView
preValidate
postValidate
I want to check if a User is saved in a session bean is logged in and if not redirect to the login site, which needs to occur before view-param conversion phase since the used converter depends on the logged in User. 'preValidate' seems to take place after conversion and so I need an earlier event.
<f:event type="preRenderView" listener="#{beanA.checkLoggedIn()}"/>
<f:viewParam name="param" value="#{beanB.param}" converter="#{beanB.converter}" required="true"/>
I could have put 'checkLoggedIn()' in 'beanB' too, but tried to use a separate request scoped bean just for the check so that I could reuse it easily.
What is the execution order of those?
postAddToView runs right after the component is added to view during view build time (which is usually during restore view phase, but can also be during render response phase, e.g. navigation).
preValidate runs right before the component is to be validated (which is usually during validations phase, but can also be apply request values phase if immediate="true").
postValidate runs right after the component is been validated (which is usually during validations phase, but can also be apply request values phase if immediate="true").
preRenderView runs right before the view is rendered during render response phase.
preRenderComponent runs right before the component is rendered during render response phase.
Click the links to see detailed description in javadoc introduction.
I want to check if a User is saved in a session bean is logged in and if not redirect to the login site, which needs to occur before view-param conversion phase since the used converter depends on the logged in User. 'preValidate' seems to take place after conversion and so I need an earlier event.
You should use a simple servlet filter for this, not a JSF event. I've posted several examples before:
Is there any easy way to preprocess and redirect GET requests?
Are there some issue at inserting some check into template?

Persist url parameters across requests

I am using Spring MVC. There is a requirement that some user selections remain globally and always in the url parameter. I might also be able to remove it with code at will.
Is there something like Persistent Page Data(like in Tapestry http://tapestry.apache.org/persistent-page-data.html) for Spring MVC.
A link to a similar quesion thats unanswered: http://osdir.com/ml/java.appfuse.user/2005-08/msg00507.html
Thanks
Update
Eventually I used a simple technique, where:
1. I would capture the current page url with query paramters.
2. Add or replace the new parameters into this url.
<c:set var="contextPath" value="${pageContext.request.contextPath}"></c:set>
<c:set var="servletPath" value="${requestScope['javax.servlet.forward.servlet_path']}"></c:set>
<c:set var="currentPath" value="${contextPath}${servletPath}"></c:set>
ageone
where replaceUrlParameter() uses regex to replace or add the query parameter.
Keep this parameters in session and write the Servlet Filter that would add them to any request or would modify request URL so they are visible in URL.

How to know whether JSF bean setter is invoked from AJAX event or as part of form POST processing

I have a form that contains a Part Number inputText field and some other fields that represent the attributes of a part. If the user enters an existing part number, I want to populate the other fields with the part's existing attributes. The operator then has the option to change Part Number to something else (essentially creating a new part using the existing part as a template) and/or modify its attributes. I have an AJAX event defined to update the model when Part Number changes, so I can retrieve the attributes from the database:
<f:ajax event="valueChange" execute="#this" render="partlength" />
My question is this: How does the Part Number setter (e.g. setPartNumber() ) know whether it is being invoked as part of an AJAX event, in which case I want to fetch the attributes, or as part of the Update Model Values phase of the form being posted, in which case I don't? Or is there a better way to accomplish what I'm trying to do?
You can determine by PartialViewContext#isAjaxRequest() whether the current request is an ajax request or not. You can obtain the PartialViewContext by FacesContext#getPartialViewContext().
if (FacesContext.getCurrentInstance().getPartialViewContext().isAjaxRequest()) {
// The current request is an ajax request.
}
An alternative is to just do the job in the listener method of <f:ajax> instead of in the getter/setter (doing business job in getters/setters is a poor practice anyway):
<f:ajax listener="#{bean.listener}" render="partlength" />
(note that I omitted the event and execute attributes as you've used the default values already)

Passing request scoped beans from one page to another

If I have a request scope bean on a page in JSF2....how do I pass it to another page (I'm using JSF2 with Spring)?
I've tried the following but it doesnt work:
<h:commandButton action="complete.xhtml?faces-redirect=true" value="Confirm Booking">
<f:setPropertyActionListener target="#{quoteHolder.item}" value="#{quoteHolder.item}"/>
</h:commandButton>
action="complete.xhtml?faces-redirect=true"
You're sending a redirect. The <f:setPropertyActionListener> won't help much here as the request scoped bean will be garbaged after the invoke action phase anyway.
You have basically the following options:
Send all the data as request parameter(s) instead (conversion to/from String necessary!)
Don't send a redirect (the <f:setPropertyActionListener> becomes superfluous then)
Store it in a session scoped bean (not recommended! may be bad for user experience).

Resources