CDI Conversation without ending - jsf

In my JSF project I have a multi page wizard. I am using a #ConversationScoped CDI bean for that wizard. The conversation works well. When user comes to the first page of the wizard, new conversation begins. When user clicks a submit button in any page, the conversation ends. But i have several questions.
What happens if, at the middle of the wizard, the user entered a url in address bar and navigated to another page without clicking a submit button, do I still have a way to end the conversation?
Should I bother about this situation or can accumulating such non-ended conversations become a overhead for my application?

Most applications ends up with some kind of system that tracks where the user is currently at. This is supposed to be helped by #FlowScoped in JSF 2.2. If you can use that instead then everything should be managed for you. It should be really easy to find examples.
If you can't use FlowScoped and want to stay on #ConversationScoped you must implement your own system for tracking where the user is at. When the user is no longer in your flow you end the conversation.
#Inject Conversation conversation;
// conversation.end();
Here is a useful part for implementing this: How to cleanly end a CDI #ConversationScoped
However I would go for http://deltaspike.apache.org/core.html and use: To get the conversation.
MyBean myBean = BeanProvider.getContextualReference(MyBean.class, false);
Personally I would do an extension to the type safe navigation in Deltaspikes JSF module to achieve the same thing if I could not use FlowScoped.
Good luck

Related

JSF Security: bean method accessibilty

I have a basic question about JSF ManagedBeans for which I can't find a answer.
Suppose I have a bean MyBean with two methods method1 and method2 and a JSF page with a command link
<h:commandLink action="#{myBean.method1}">
</h:commandLink>
Is it possible for someone to analyse the source code of the page and call method2 instead of method1?
Answer
No, this is not possible by design.
Reasoning
Technically the client can only tell the server "The user clicked a html element with a certain id".
This event is then processed by JSF on the server-side, the component with the corresponding id is looked up and in this case the method "#{myBean.method1}" is executed.
As you can see, the client can not[!] tell the server what to do with this event.
Sources
JSF 2.2 Spec - 3.4 Event and Listener Model
Caveat
JSF is stateful and there are multiple ways to hold this state. The default is to hold state information server-side (e.g. in the users HttpSession).
Another option is to transfer (encrypted) state to and from the client. This is still conceptionally secure, but there *might* be bugs with client side state saving. Such a bug *could* be exploitable to do something like you described.
Yes, it is always possible to modify code (or markup-language) on the client-side. Your "action" will be called through some forms and/or Javascript-Methods - everything visible to experienced users.
But that's not an issue of JSF-2 only - this applies for every language which allows insights from the client side.
You shouldn't apply "security through obscurity" (https://en.wikipedia.org/wiki/Security_through_obscurity) but rather make sure, that you can handle this on the server-side.
If a user, who has access to two urls modifies url1 to url2 - that's fine, why not? (Could be bookmarked) - But YOU should take care of the modified request, if he is not allowed to access url2.

j_security_check not redirecting to welcome page - successful login event listener?

For ages I've been puzzled about why after login I sometimes don't directed to the application welcome page. I've finally figured it out (years after everyone else):
I login successfully via j_security_check and go to the welcome page
wait for session timeout
click on h:link which sends a GET request
because it's a GET and not a POST my custom ViewExpiredException
handler doesn't kick in
container security redirects to the login page because the session
has timed out. Because of the session timeout+container security the
get request (from h:link) isn't seen by the application, in either a phase listener
or filter.
I successfully login again
j_security_check redirects me to the page which triggered the
authentication, in this case the target of the GET request.
The last bit I'd not understood, I assumed it would always go to the welcome page.
My problem is that my current design requires that after login I always show the welcome page. The welcome page has a preRenderView event which sets up some context information in a session scoped bean after login and increments a few counters etc...
This context information is required by backing bean code for other pages, and presently if I don't go through the welcome page first there'll be an exception.
In terms of fixing it I've looked at the following options:
Ideally there'd be an #PostLogin method that could be called, which would cleanly solve all my problems. I use JSF (Mojarra) with Myfaces CODI but I don't see anything which does what I want.
I could add some more code to my filter, but I need to persist some data (i.e. login count), it doesn't look like a nice option. Maybe I'm wrong.
I make all the preRenderView methods of potential targets of j_security_check (pages called with GET) handle the case where they are called directly from j_seecurity_check. I can see this being what I have to do but it seems like a lot of hassle.
Write a Server Authentication Module for glassfish to override j_security_check behavior.
How is this normally handled? I've started hitting this problem after moving to GETs for simple navigation cases after years of abusing POSTs, and the custom exception handler doesn't work. If anyone has any guidance on this issue I'd appreciate it, at least I know what's going on now. Hopefully I've missed something obvious!
Thanks
O/S
Ideally there'd be an #PostLogin method that could be called, which would cleanly solve all my problems. I use JSF (Mojarra) with Myfaces CODI but I don't see anything which does what I want.
There is indeed no such thing.
I could add some more code to my filter, but I need to persist some data (i.e. login count), it doesn't look like a nice option. Maybe I'm wrong.
That would indeed be the "easiest" way. Basically:
UserPrincipal user = request.getUserPrincipal();
HttpSession session = request.getSession();
if (user != null && session.getAttribute("user") == null) {
session.setAttribute("user", user);
// First-time login. You can do your intercepting thing here.
response.sendRedirect(request.getContextPath() + "/welcome.xhtml");
}
I make all the preRenderView methods of potential targets of j_security_check (pages called with GET) handle the case where they are called directly from j_seecurity_check. I can see this being what I have to do but it seems like a lot of hassle.
That's not DRY.
Write a Server Authentication Module for glassfish to override j_security_check behavior.
Can't answer that as I've never done that.

Jsf: what bean scope for a two page master-detail?

In a jsf application I have a table with summarized data. If I'm interested in the details I can click on a row an see the details in another page.
If the managed bean of the 'master' page is ion view scope it is re-created every time I return back from the 'detail' page and I don't think it is a good idea if the user is supposed to check the details more times. I can solve putting the bean in sessions cope but this way the bean (and the data) are kept in memory also when the user is interacting with the application in a completely different section. Probably I would need a custom scope but:
the documentation about custom scope is poor and I'm a bit frightened about people complaining it has bugs and doesn't work well.
the scenario I'm dealing with seems to me quite general, so I wonder why there is no ready solution for it.
Thanks
Filippo
If the detail page has to be idempotent (i.e. it's permalinkable, bookmarkable, searchbot-crawlable), just use two request or view scoped beans and use a GET link with the entity ID as request parameter to go from master page to detail page. See also Creating master-detail pages for entities, how to link them and which bean scope to choose for a concrete example.
If the detail page does not need to be idempotent, then you can always conditionally render the master and detail in the very same view or even display the detail in some modal dialog from the master page on. This way you can continue with a single view scoped bean.
In JSF side you must not be too much worried about the DB performance cost. Rather configure and finetune it in the persistence layer. In JPA for example you can setup a second level cache. If you've much more than 500~1000 items, then consider database-level pagination.
It may be valid to reload the master page each time e.g. if the data could have changed after viewing the details page. However, if you want to keep the data available for longer than #ViewScoped your options are:
You should be using JEE6 of which JSF 2.0 is a part of, so look at Conversation Scope (part of CDI)
Some additional scopes for JEE6 CDI is available through the MyFaces CODI
Potentially use Session Scope and make sure you tidy up when a Request hits which is not for the Master or Details page
Rework your design to use Ajax, so if clicking a record on the Master page its details load in the same view. You could then use #ViewScoped
My preference would be to look at the Conversation Scope. You don't mention which JSF implementation you are running or in which environment.

Best way to implement user login page in JSF

What's best way to implement login page in JSF 1.2? If session is timeout, use will be redirected to login in page. i found 2 ways to do it on internet.
use PhaseListener ->
http://www.jsfcentral.com/listings/A92000?link
use filter ->
What is the correct way to implement login with redirect using JSF 2.0?.
also i want user go through an agreement page right after login page. user need to click on "agree" button to continue to use the system.
can anyone tell me which option is better or if there is a better way to implement this.
thank you,
What's best way to implement login page in JSF 1.2?
Just use a JSP/Facelet page with a <h:form> and appropriate input elements and a backing bean which puts the user in an injected session scoped bean.
If session is timeout, use will be redirected to login in page. i found 2 ways to do it on internet.
Definitely use a Filter. A PhaseListener has too much overhead for this simple use case. You're not interested in filtering/modifying the JSF lifecycle, but just on filtering/modifying HTTP requests.
also i want user go through an agreement page right after login page. user need to click on "agree" button to continue to use the system.
Well, then just develop such a page? If you stucks, press Ask Question on the right top with the actual problem described in detail.
Filter is always better is meant for this, and more suitable also.
Now for your requirement ,
On successful Login
- Add managedBean holding user info to session
On acceptance of terms
- update this bean's field
and check for both the condition for rest of the pages.
no check on login page
check of bean for term page
In JSF2 it can be done using System events. In your template page put
< f:event type="preRenderView" listener="#{loginBean.checkLogin}"/>
and in loginBean ( make it session scoped ) you can do like this
public void checkLogin(ComponentSystemEvent event) {
// loggedIn is a boolean variable when sucessfully logged in make it true and at logout make it false.
if (!loggedIn) {
FacesContext context = FacesContext.getCurrentInstance();
ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler)
context.getApplication().getNavigationHandler();
handler.performNavigation("login");
}
}

JSF session scope beans with Tabbed browsing

We have the following problem...
Application's environment:
JSF, Richfaces, a4J
Consider having the following scenario:
The user logs into the system
The user navigates to a new page which consists of an a4j form containing a4j components, the user fills into the form but doesn't submit.
The user opens a new Tab and opens the same URL and fill in the new form with new data
The user returns to his first Tab and submits the information (Note: All beans are defined are session scope)
Result:
The submitted information is the information from the second Tab but submitted from the first Tab, which is expected as long as the beans are defined as session scope.
Problem:
We need to get the behavior of a request scope (i.e: dealing with new tab as a new request although the bean is defined as a session scope).
Notes:
When defining the bean scope as a request scope the partial Ajax response from individual components in the same form, resets the other components since they are not submitted yet.
Any suggestions ?
--
Thanks so much
This is a well known problem for Web applications.
Of course you can try to solve this problem using more custom code
but my quick suggestion is to use the seam framework which solves exactly this.
Seam is a superset of JSF and introduces a new conversation scope for
beans that does exactly what you want.
Seam supports richfaces natively (both are projects of JBoss/Redhat) so
you should not expect any problems with integration.
What is the reason the bean needs to be in session scope ?
If this is only to get ajax functionality then you can change the bean to request and use the a4j:keepAlive tag.
a4j:keepAlive extends the live cycle for the request scope bean, your bean instance then acts like it is in session scope for ajax requests. When the user opens two of the same page they are using two different bean instances.

Resources