*
The moose likes JSF and the fly likes forms authentication (j_security_check) with JSF Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » JSF
Bookmark "forms authentication (j_security_check) with JSF" Watch "forms authentication (j_security_check) with JSF" New topic
Author

forms authentication (j_security_check) with JSF

azhar bharat
Ranch Hand

Joined: Jul 17, 2006
Posts: 87
How can I have forms authentication with JSF using Tomcat realm & j_security_check?

I have done j_security_check login on pure jsp page. But little confused on how to do it using JSF.
Should I have a backing bean? Do I need to write navigation rules since this is already handled by the container? etc..
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15952
    
  19

You can't. Use a regular JSP for your login and loginfail pages.

Unlike the normal application webpages, container-based logins via forms are managed directly by the application container (Tomcat), and the infrastructure you need to run JSF isn't available.

Container-based login prompts are presented whenever a URL maps to a secured part of the website and the user isn't already logged in. This is one of the major strengths of container-based security. As long as critical functions live behind a secured URL, there's no way an attacker can even GET to the secured functions without a valid login. Many of the DIY frameworks assume that logins came from the "right" place, so they get easily defeated by simply coming from a "wrong" place. Or, if you're going to the trouble of injecting security code ahead of sensitive functions, you have to muddy the application code by manually placing security code in front of every sensitive function. And hope that you didn't forget one, or that a later maintenance programmer doesn't either forget or simply doesn't know how to do it right (since it's not like there's a book on it down at Barnes & Noble).

And, based on what I've seen over the last several years working with moderately-experienced programmers, you might as well cut your own throat and be done with it. Filters can help, but that's just a poor mimic of what the container does for free.

But that's another story. Returning to your specific problem, when a sensitive URL request comes in, the container shunts the whole request aside; places it "on hold". It then proceeds to present login/loginfail pages until either it gets a valid login or the user gives up. If the login is valid, the "on hold" request is pulled off the side and allowed to process exactly as if the user had been logged in all along.

So the reason that you can't use JSF for login pages, is that the look-aside mechanism for logins can't route the login page URL (which is limited anyway) to a servlet. Specifically, the JSF FacesServlet.

Not everybody likes this. I just had a discussion with a client who wanted a whole raft of menus and other decorations on the login page. The problem with that idea, as I told him, is that when you're in login mode, the LAST thing you should do is allow alternative logic paths off the login process. To me, login should be a simple process with no distractions and definitely no complications. The rest of the site can do whatever it wants, but the gatekeeper is strictly to the point.

So in sum: No. There's nothing you need to do (or can do) in JSF for logins. No logic, no backing beans, no navigation rules. The only thing different about JSF has to do with URLs. Since the container-based security system keys off URL patterns, you have to make sure that you don't transfer over to a sensitive function while still operating under a non-restricted URL. Which can be a major issue in JSF, since the URL isn't as firmly tied to the function being invoked. You can use the <redirect/> element in faces-config to force the request to be rerouted back under the secured URL and thus properly protected.


Customer surveys are for companies who didn't pay proper attention to begin with.
Piotr Swiecicki
Greenhorn

Joined: Nov 16, 2006
Posts: 17
Tim Holloway wrote:You can't. Use a regular JSP for your login and loginfail pages.

Unlike the normal application webpages, container-based logins via forms are managed directly by the application container (Tomcat), and the infrastructure you need to run JSF isn't available.
....


I don't agree. Obviously the action of the login form has to be handled by container itself, so it can be only j_security_check servlet and it is not possible to inject any custom logic here. But still to render the login form and login form errors we can use whatever technology we want. I have just implemented a login page using JSF 1.2 and Facelets recently, it works properly in both Tomcat and Glassfish servers.

It is standard web application, with JSF and Facelets configured in standard way, and with the following configuration in the web.xml:
azhar bharat
Ranch Hand

Joined: Jul 17, 2006
Posts: 87
Yes, I do understand that login page should have only login form etc..
But, I am not the one who takes decisions, the client does.

There are other JSF elements required on the page, and I need to use the JSF validations too.

Is this not possible? It seems strange that I cannot use security features along with JSF.
Piotr Swiecicki
Greenhorn

Joined: Nov 16, 2006
Posts: 17
azhar bharat wrote:Yes, I do understand that login page should have only login form etc..
But, I am not the one who takes decisions, the client does.

There are other JSF elements required on the page, and I need to use the JSF validations too.

Is this not possible? It seems strange that I cannot use security features along with JSF.


Maybe I was not clear enough, but I was trying to say that it is possible and I have managed to achieve this without any difficulty. You can have fully working JSF page acting as a login page, like I have done.
azhar bharat
Ranch Hand

Joined: Jul 17, 2006
Posts: 87
Piotr Swiecicki wrote:

Maybe I was not clear enough, but I was trying to say that it is possible and I have managed to achieve this without any difficulty. You can have fully working JSF page acting as a login page, like I have done.


Can you explain in detail how you did this.
let us say that i have a page called login.jsf
I have a jsf inputText(j_username) and inputSecret(j_password) and a commandButton (with action="j_security_check") in the form on the page.
Do I have to create a backing bean for these components?
I assume no navigation is required.
Piotr Swiecicki
Greenhorn

Joined: Nov 16, 2006
Posts: 17
azhar bharat wrote:
Piotr Swiecicki wrote:

Maybe I was not clear enough, but I was trying to say that it is possible and I have managed to achieve this without any difficulty. You can have fully working JSF page acting as a login page, like I have done.


Can you explain in detail how you did this.
let us say that i have a page called login.jsf
I have a jsf inputText(j_username) and inputSecret(j_password) and a commandButton (with action="j_security_check") in the form on the page.
Do I have to create a backing bean for these components?
I assume no navigation is required.


Ok, you cannot use h:form tag as it will render html form tag with action pointing to the current JSF view - and this conflicts with container based authentication requirements, as it required that login form is submitted to the j_security_check. So you have to use standard html form on the login page.

And obviously you can't add any validators to username/password fields - but I hope this is not what you want, after all you decided to use container based authentication, so it is the container who responsible for validating username/password, not your application, isn't it?

In my case login page looks like (it depends on template.xhtml template, which is not importat for this example I believe):
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15952
    
  19

That's not a JSF page - just a Facelets page.

Trust me on this one - I've had to work inside Tomcat itself, and the routing to the Faces servlet that JSF requires isn't provided. I had the same problem with Struts. I need to refresh my memory on how Facelets is doing what it's doing, but Facelets doesn't have a controlling servlet so it doesn't get frustrated by lack of full-fledged routing.

There is no "j_security_check servlet". The security check is done directly in the core Tomcat code. Without going back and looking, I think it's in one of the standard Valves, but if you're really interested, I can look it up.

You can href-include anything you want in the login page as long as it's not dependent on being already logged in. But the login page itself is limited.


There are other JSF elements required on the page, and I need to use the JSF validations too.


This isn't one of those deals where you have a "normal" web page and there's a place to login in the corner is it? That can't be done using container-based security (at least directly).

As I mentioned before, Form-based security is injected into the page flow by the container at need. It's not something that you can call explicitly. The field names "j_username" and "j_password" have no magic significance. It's simply that when Tomcat security looks up the login page from web.xml and presents it, it will look in the user's login request and do "request.getParameter("j_username")" and password against that data. At no other time and in no other situation are those field names any different than any other field names. It's the context that matters, not the name itself. And, while there's not actually a formal j_security_check servlet in Tomcat, the behavior is pretty much the same as if there were. You can't add extra logic to anyone else's servlet if you don't have the source code, so it's equally impossible to add extra logic to the Tomcat "security servlet".

The problem with trying to do business logic at the same time you're authenticating is that it's perilous to begin with and potentially complex to implement. If you enter a login ID and password at the same time as data entry, does the business logic take place before or after the security level is boosted? What do you do with the data if the login fails? Worse yet, what if the way the data is handled is decided by the user's security roles? What if some parts of the form are secure-only and some parts aren't? And that's not even counting what happens when you add AJAX to the mix.

J2EE security doesn't even attempt to deal with this. It provides the guard who checks your papers at the border and that's it. The guard doesn't do money exchanges, recommend hotels, or anything else - just passes or rejects applicants. Once you're in, you have the benefits of the security context. Until then, you don't. It's very black-and-white, and while mostly I dislike bipolar solutions, security is one area where I make an exception.
Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2835
    
  11

Sorry to dredge up an old thread, but I am trying to get something like this working with JSF 1.2, RichFaces 3.3.1, and JBoss 4.2.3. Basically, the application now uses login.jsp to login, but they want to add the standard header bar and right panel with site information into the page. Those sections in the other pages use RichFace stylings, so I would prefer the login to be a JSF. (I don't understand Tim's distinction here between a Facelet page and a JSF.) I tried Piotr's solution, with a couple of modifications: 1) I added a submit button to login form, that seemed to be missing, and 2) I put /login.jsf, not /login.xhtml into web.xml, since otherwise the tags weren't parsed and converted to HTML.

I got some very strange results. The login page came up OK when I tried to open a protected page (home.jsf), but when I looked into the various <link> and <script> includes, for example skinning.js.jsf, they all just include the HTML text of my login page, instead of the style rules and JavaScript they contain on the regular JSF pages. I have no idea how to explain this. When I submitted the form, instead of being redirected to home.jsf as I expected, I instead got the contents of skinning.js.jsf in my browser window, though at least it contained the right information, not a duplication of the login page HTML.

I found another example here, which claimed that the only way for this to work was to use a regular JSF page but change the <h:form> tag to a regular HTML <form> tag and surround that with <f:verbatim></f:verbatim>. and do the same with </form>. That also did not work. It claimed I had no closing form tag.

I just want to include RichFaces tags in my login page. ui (facelet), h, and f tags would also be useful, but not as crucial. Is there any way to do this?
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15952
    
  19

Actually, it probably would have been better to create a new thread and link to the old one, but the zombie's out of the grave now, so...

For myself, I do not want any menus, animations, or other decorations on my login pages.

Psychologically, I want the login page to have all the warm and fuzzy of an East German Checkpoint (or should I update that considering current events?). At any rate, I want it to mean business and no nonsense about it, so that it won't encourage people to play games.

Functionally, although I trust container-managed security. I still dislike putting anything on the security pages that promises a potential end-run around security. Like menus.

I've long had problems with inclusions on login pages, especially in older versions of Tomcat, where I suspect that the normal URL processing was completely derailed while a login was pending. These days, though I'm suspecting that your links may be relative to a URL base that doesn't apply. Since the login page is presented by the container security subsystem instead of the normal application URL processor the "real" URL may not be what you think it is. And therefore neither is its URL base.
Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2835
    
  11

Thanks Tim. Actually, I don't want menus either. I just want the header bar that the other pages use, sans links. (Strictly speaking, I don't even want that, but I'm being told to put it in.) It's styled with the RichFace classes though, and I'd rather not try to duplicate the styling in plain HTML. Also there are right and left panels, with information, not menus, which I'd also like to take on the RichFaces styles.

I'm trying again now, with our regular login.jsp (with a few clerical changes) converted to XHTML, and login.jsf in the web.xml as the form-login-page. It's about the same thing, except instead of loading up skinning.js.jsf after the login, I get spacer.gif.jsf instead. These are both GETs I can see when sniffing the load of the login page, but I don't see how either one gets into the forward from the j_security_check.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15952
    
  19

The biggest problem with attempting to use JSF on a login form is that the login page form isn't routed to the FacesServlet, it's routed to a processor that's internal to the server, and that processor basically has the following logic:

1. Collect userid from the incoming form
2. Collect password from the incoming form
3. Invoke the configured authenticator (Realm) module's "authenticate" routine, passing userid and password as parameters.

ON SUCCESS, pull the previous URL off hold and resubmit it internally.

ON FAILURE, display the loginfail page.

As far as getting the overall site look-and-feel on a JSP, JSF can actually be an advantage, since if you've followed good practices, you can replace most of the screen areas with div, span and table elements and simply apply the same CSS styles to the crude HTML blocks as you would to jsf panelGrid and similar objects. I believe you can even replace outputText elements with JSTL cut elements, as long as you define the backing beans JSP-style on the page. Although if you haven't already constructed the beans in question by visiting a JSF page first, you won't get the managed property "freebies".
Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2835
    
  11

Maybe I'm not understanding your suggestion. It seems to me the RichFaces styles are defined by CSS files that are generated on-the-fly. For example, viewing the source of my home.jsf, I see:



and five or six others.

I'm guessing the eAFj-rlJKnT5DGkAECkDdw part of that URI will change from time to time. The 3.3.1 part will also change when we change versions, but that would be easier to deal with.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15952
    
  19

Actually, RichFaces is skinnable. There are 4 or 5 pre-defined "skins" in the package, and if you prefer, you can provide your own. Although the URL may vary, the actual stylenames for specific RichFaces components and their cub-components are standard and they are documented for each tag type in the RichFaces manual.

Plus, you can add (cascade) your own styles on top of the RichFaces styles if you like. For example, when you want a RichFaces Panel to be a fixed width and/or height.

I'm not sure what it takes to get a particular set of styles loaded on a non-JSF page, but I would not be surprised to see that there's something available for that purpose.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15952
    
  19

Incidentally, I'm not 100% sure about the portability of this, but it is potentially possible to use JSF to format the login page, even though JSF cannot process the login itself. That would depend on whether or not the container routes the login page URL through the FacesServlet before presenting the page to the user. Which would solve the use of RichFaces display components.

To make such a page login, make the actual login form be HTML and not JSF and code it according to the j2EE standards for login forms. Use the HTML form tag instead of the JSF form, and make sure you code an HTML SUBMIT button and not a JSF commandButton!

I've done something similar, although in my case, it was a workaround for Yet Another IE Annoyance, where it was easier to code an HTML form that submitted to a PrettyFaces URL than to fight the IE quirks and use JSF.
Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2835
    
  11

Having a regular HTML form on a JSF page would bring us back to Piotr's solution, which isn't working for me. The tags do render correctly into HTML, and the link and script references to RichFaces styles and scripts get put into the header the same way they would for any other JSF. However ... and I know this bizarre ... when I drill down into those referenced links and script files, the contents contain a duplication of the login page's HTML, rather than the CSS and JS code they should contain. So there's that problem, plus the fact that the redirect back to the requested page (home.jsf) after a successful login doesn't work, and I get the (empty) content of spacer.gif.jsf in my browser window instead, though previously I was getting skinning.js.jsf.

Interestingly, if I hit my login.jsf page directly, not get redirected there via the container-managed security, then the contents of the RichFace style and script files are fine.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15952
    
  19

Take a closer look at what was being proposed. A commandButton on an h:form. That's what Piotr was discouraging. It has to be an HTML FORM and an HTML SUBMIT button. I will guarantee that that works as long as the raw HTML on the JSF-generated page is conformant to HTML standards. Which is should be. As I said, I've done something similar.

On the other hand, I cannot explain why included items don't render properly except to point out that I'm not sure about any particular version of any particular webapp server being capable of doing first-class URL routing while login processing is in progress. Some people claim it works, but I tried with raw JSP+resources and with Struts, and neither gave me any joy. I haven't tried recent-vintage servers, however.

2 notes:

1. It should go without saying that no protected resource should be referenced on a login page. After all, if a script or image can only be accessed by a logged-in user, the login page is obviously the wrong place to put it!

2. You cannot put a redirect on a login page to go to a "home" page. A successful login is simply going to cause the original protected URL that initiated the login process out of storage and re-submit it. You can redirect to a home page (although this negates the concept of bookmarkable protected pages). But you have to do it in a servlet filter when the deferred URL is resubmitted.
Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2835
    
  11

Hmm, where was a command button on an h:form being proposed? In any case, that's not what I'm trying to do. It seems like you're guaranteeing something will work that I've just proven doesn't work. Just to be sure, I simplified my login.xhtml to:



which renders as:



Again, the referenced files, which should contain RichFaces CSS and JavaScript code instead just contain the same contents as the rendered page. Logging in brings up the skinning.js.jsf page, not home.jsf, which is the URL I originally browsed to.

I don't have any redirects on my login page to go to a home page. I was browsing to my login.jsf directly only to see how it would render. I actually don't want to do anything to subvert the normal container managed security. I just want to be able to use RichFaces tags on the login page and have them styled the way they would be in the rest of the application.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15952
    
  19

Login Pages are not intended to be directly invoked. The action "j_security_check" cannot be processed as a direct URL, only in response to the container having posted the Login page the client. That's not a JSF thing, it's a J2EE thing. J2EE's authentication can not be invoked directly, it's only activated when you attempt to access a protected URL. That keeps people from coding apps where security loopholes might bypass login, and it makes apps able to be secured by Single Signon without changes. You might already know that, but I wanted to nail it down.

Regardless, the login form itself should work as long as it's in syntactically valid HTML. Stuff like an HTML form embedded in an h:form, for example, is not going to be valid, just as embedding an HTML form inside another HTML form isn't valid. The only restriction is that the action cannot be fired stand-alone, only as a response to a container validation request. I suspect that the jsessionid that gets tacked onto the outbound URL is bound up in that as well.


Stuff like "/MyApp/a4j/s/3_3_1.GAorg/richfaces/renderkit/html/css/basic_classes.xcss/DATB/eAF7sqpgb-jyGdIAFrMEaw__.jsf" is not a Page, nor is it a file. It's a URL. In J2EE, URLs are first parsed agains the URL patterns for the webapp's servlets (as defined in your web.xml). Next they are checked against the container's patterns (this is how ".jsp" files are understood). Only if no URL patterns are matched is the default URL processor invoked, which is where the processor that snips off the server and web context part and uses the rest of the URL as as a WAR resource path (what people like to call "files", even though a "file" in a ZIP/JAR file isn't truly a file until you unzip it). If the URL matches a URL rule, the corresponding rule processor has total control about what to do with the URL. In the case of RichFaces CSS, part of what the RichFaces sub-processor does is figure which skin is turned on (it gets that from web.xml) and returns the appropriate CSS resource. So it couldn't ever truly be a file, just a selection from a set of files (or their equivalents).

What that mostly means in practical terms is that there's no predicting what will actually come back when you issue that URL directly or that you'll get the same results every time. It depends on how the URL is being scanned and if JSF/RichFaces is doing the scanning. If that's what you're doing. If you're using Firefox plus the FireBug debugger plugin, you can display all the URLs processed for a given page request and that gives a somewhat more accurate indication.

The real question, however, no matter how you analyze it is "Is the "display login page" request going to be passed through the FacesServlet"? The answer is: I don't know, but if it isn't, forget about attempting to use the RichFaces CSS classes. Supply your own equivalents.

BTW, the "commandButton" thing was was azhar wanted to do. Piotr was warning him not to. I was just repeating the warning.

Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2835
    
  11

Yes, I agree. I actually don't have any intention of invoking the login page directly. I did that as sort of an experiment to see if the RichFace styles would appear, which they did. When I hit the login page indirectly as the result of going to a protected page, the RichFace styles are not applied, and that's because the link and script URL references that the FacesServlet puts in when rendering the page into HTML, refer to (virtual) files that don't contain CSS and JavaScript as normal, but actually contain the rendered HTML of the login page. Weird right? Again, when I hit the login page directly (only as an experiment), the contents of the (virtual) files contain CSS and JavaScript as expected. In short, when I hit the login the right way, it looks wrong, and when I hit it the wrong way, it looks right. Sad Greg.

I'm coming to the conclusion that what I want to do is impossible, despite other people swearing they've got it to work (though not specifically on JBoss). I'll either have to figure out how to generate the RichFace headers into a normal JSP, or convince the customers that the login page doesn't need to have the look and feel of the rest of the site.
Srikanth Nittala
Greenhorn

Joined: Sep 24, 2006
Posts: 22
We use a similar set up in our project but face the following wierd issue.
We are using container managed security with form based authentication.(a simple xhtml form with j_username,j_password and j_security_check), JSF with OC4J.

We have to prevent the possible viewing of private and sensitive information by unauthorized users so we do not want the browser to cache any information. We have created a JSF listener to append a no-cache header to pages. This is working to prevent the viewing of prior pages by using the browser back button and the information should also not be available for potential abuse from the browser’s cache folder but has created a side effect.

When a user logs out of the application and then clicks the browser back button, eventually they have the option to resend or repost a request which has the j_username and j_password parameters included.

The user is re-authenticated and is able to then continue on in the application as if they had logged in again and entered their username and password.

Our application logout does invalidate the session and when the user is automatically re-authenticated, a new session with a new j_sessionid has been created.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15952
    
  19

I have never had that concern in OC4J. However, it is actually a vexation in Tomcat that if you're logged in and using SSL, Tomcat itself jams in no-cache directives into the response streams. This was killing me because there was a lot of repeated JavaScript and CSS data being downloaded and the response times were intolerable. I ended up having to do various things to restrain Tomcat's enthusiasm.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: forms authentication (j_security_check) with JSF
 
Similar Threads
Auto Login
JAAS Realm-Error
Authentication/Authorization
Securing a JSF Logon
Logging in an application from a cookie using JAAS