• Post Reply Bookmark Topic Watch Topic
  • New Topic

JSF - passing messages between request and session scoped beans  RSS feed

 
Ashley Bye
Ranch Hand
Posts: 134
2
Java Mac
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
How do I pass information between request / stateless and session / stateful beans? By way of an example I am writing a simple application that logs in a user, allows the user to do some stuff, and can log a user out. I want to be able to keep track of the logged in user so that any 'stuff' they do is only done to their data.

My initial thought was to inject a session scoped backing bean into my request scoped backing bean, but then realised this is illegal. Therefore I am a little perplexed as to how I pass information between request and session scoped beans. What I am trying to achieve is having a session bean store the current user, a token in a cookie that is unique to that user, so any requests check that the user returned when searching for the token matches that stored in the session. Alternatively, should I even be tracking the logged in user in the frontend? I don't see how this is business logic that needs to be dealt with in the backend, unlike creating, deleting, etc. Or, since data integrity is reliant on the correct data being altered for the correct user, should maintaining track of the user be dealt with here? This could be achieved with a stateful bean that the session scoped bean checks with. Methods would then check that the user is only altering data they own. This approach doesn't seem very intuitive though, but as always I'm happy to be corrected. And still have the problem of how do I get data from a session scoped / stateful bean with a request scoped / stateless bean, and how will the request / stateless bean know which instance of the session / stateful bean to communicate with?

Please could someone explain the concept behind this, either in text or with a brief example. I don't want to provide my own code since I'd like to try and fugure this out on my own rather than be handed the exact implementation.
 
Tim Holloway
Bartender
Posts: 18531
61
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, before I even get to the JSF part, I have to make my obligatory assertion that when you've written your own login code, you've effectively already been hacked. I'd point to a list of about 11 reasons why security systems designed by people who aren't full-time security experts are virtually useless, but a certain very large communications company seems to have arbitrarily unplugged some hardware at their switching office and most of my local infrastructure is offline until they get around to repairing it.

J2EE provides a ready-made security subsystem that's far more secure and better documented than anything you or your local in-house geniuses are likely to be able to afford to produce or maintain. I really wish introductory J2EE books wouldn't code examples that do "roll your own" logins. The container security systems is also integrated into the J2EE API, which is something that cannot be said of independently-created security systems.

Getting into JSF itself, forget about Request Scope. Request Scope is virtually 100% useless in JSF. That has to do with the inherent statefulness that comes from having a system that's designed with one of its primary features being multi-request conversations with a single form (otherwise known as making the user keep correcting the form input data until it is valid). Creating and destroying objects loses critical context used by that process (which, incidentally, is called "postback"). And that's what Request scope objects do - get created and destroyed on each request.

Session-scoped beans automatically know which user is which, even if you don't use any security/login at all. They do this by using a special token known as "jsessionid", which is a hash key to the server's table of user sessions. Each and every webapp user is assigned a separate and distinct HttpSession object automatically when they request a session and that jsessionid keeps track of which user has which session. The jsessionid is automatically passed back and forth to the client application (browser) using cookies, if the user has allowed cookies. If the user doesn't allow cookies, an alternative mechanism known as "URL rewriting" is used to keep the jsessionid going back and forth.

The only time there is confusion as to which user "owns" a backing bean is when the backing bean is in Application Scope. Application scope beans are shared between all users of the webapp.

 
Ashley Bye
Ranch Hand
Posts: 134
2
Java Mac
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tim Holloway wrote:J2EE provides a ready-made security subsystem that's far more secure and better documented than anything you or your local in-house geniuses are likely to be able to afford to produce or maintain.

A fair point well made. I am aware that there is a security sub-system with J2EE, but I haven't gotten around to digging into yet which is why I wanted to start with a simple system that I could then ditch in favour of that.

So if I understand correctly, for now, I should just ditch all of my request scoped beans in favour of session scoped beans (certainly those that are concerned with specific users anyway). I can then rely on the container to manage which (originally named) instance of UserBean the current user is stored in, meaning I can then inject this into other session scoped beans. In a SaleBean I would then be able to do something like:
and rely on the fact that under the hood the correct instance is being accessed for the logged in user?

You allude to it, and as yet I don't have any application for it, but how would I make sure the right session bean was injected into an application scoped bean? I draw stumps when racking my brain for a possible situation when this might be necessary. Do you have any example scenarios?
 
Tim Holloway
Bartender
Posts: 18531
61
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can use session scope or view scope. View scope is a feature (since JSF 2.0) that's basically a self-deleting session-scope object. That is, it's bound to a particular page (View) and when you leave that page for a new page, JSF automatically deletes it. That keeps the app from getting progressively more cluttered with idle session objects.

You don't have to do a "getCurrentUser", because in session/view scope, you're always the current user. If you wanted to a user to be able to pull his/her sales records and needed the user's ID, you might have a construct like this:



JSFUtils is a class I design to hide framework-specific code from the rest of the webapp. It simplifies webapp business logic, allows me to test offline, and makes the webapp's components more re-usable. The JSFUtils getUserId method, for example, uses the FacesContext to get access to the HttpServletRequest object, which returns the current logged-in user's ID via its getRemoteUser() method. So there's no need for any JSF or HTTPServlet objects or methods in the actual backing bean - they're abstracted away in JSFUtils.
 
Ashley Bye
Ranch Hand
Posts: 134
2
Java Mac
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Tim, that's veyr helpful. I'll go have a play with this later tonight and see what I come up with.
 
Ashley Bye
Ranch Hand
Posts: 134
2
Java Mac
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And to further mention my whole user login example above it would appear we even have our own JR journal entry on the subject of JAAS dating back to '08. I'll have to have a read through the Oracle JAAS tutorial to see what has changed, but a quick skim of the EE Security tutorial looks like there is a lot more to it than just JAAS.
 
Tim Holloway
Bartender
Posts: 18531
61
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
JAAS and J2EE Container-Managed Security are very different things.

JAAS is a general-purpose system (API) for authenticating and authorizing which can be used directly by any app that would like to add security features.

J2EE Container security is a system specifically for providing authentication and role-based access control and APIs solely to J2EE webapps.

One of the primary differences between the two - besides basic intent - is that J2EE Container security - like its name implies - provides security at the container (server) level, rather than via code within the webapp itself. If I request a page (URL) that I am not authorized for, the container security will block access before the request can get anywhere near any application code, and if a request cannot reach code, it cannot exploit possible loopholes in the code.

Likewise, the container ensures that no requests are made to secured URLs without first identifying (authenticating) the user (and thus obtaining a list of the roles, if any, that that user is authorized for). This enforcement, again, is done before any application logic is visible. One of the most common ways for non-technical people to defeat DIY-style security systems is to simply skip past the login screen and go straight to the allegedly secured URL. Container security does not allow this. No matter [i/where[/i] you come from, access by an unauthenticated user of a secured URL will immediately cause the server to "park" the URL request and present a login. If the user logs in OK, the original request proceeds. Otherwise, the original request remains blocked. No login code exists within the webapp itself.

J2EE container security is handled via plug-in server modules called Realms. Servers typically some with several different Realms to choose from. The easiest one for Tomcat users is the MemoryRealm and its relatives, which simply define the users, passwords and role mappings in an XML file (tomcat-users.xml). Other popular Realms include JDBC (using a database to hold account information) and LDAP (including Active Directory). You can also create a custom Realm. I've used WebServices as the basis for a Realm, as an example. And if you like JAAS, there's even a JAAS Realm.

The Realms, as I said, are plug-compatible. That means that you can test using a MemoryRealm, then put the webapp into production on a server that uses a JDBC Realm and not have to make any changes to the webapp itself.
 
Ashley Bye
Ranch Hand
Posts: 134
2
Java Mac
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is actually very interesting stuff. I like it, although it will take some time and playing to get my head around it. I'd just dug out the JSR 342 (EE Spec) and started reading through the security section in that. I might have to print a copy - it's quite wordy but actually very useful for getting the overall intent of the various components of the EE platform.
 
Tim Holloway
Bartender
Posts: 18531
61
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Specs can be wordy. Fortunately, application is simple. You define roles and URL patterns/role maps in web.xml, plus transport guarantees. You may also put in some extra qualifications in the application code, but that's almost entirely either just getting the user ID or checking to see if the user is authorized for a role.

The server-side security setup is documented in the server's own documentation, since it varies according to what server you use.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!