I've been asked by a freelancer friend of mine to join him on a JSF 2.0 project, and I'm slowly picking up speed and putting the pieces together. Coming from a Windows Forms .NET world, I have a lot to learn to say the least.
My major concern is with the lack of apparent consensus on how to protect a JSF application.
Some methods have been proposed here on SO, including using Spring security, Seam security, custom phase listeners, or simply using the rendered="#{...}" attribute to show/hide components based on user authentication.
I have tried to implement some of these methods, for example Spring security, only to find out that it gets easily defeated by the JSF navigation mechanism that forwards to views instead of redirecting. In other words, Spring security will work fine if the user types in the url of a secured page directly, but not if a h:commandButton's action takes him there.
In view of this, some have suggested to force a redirect by using "faces-redirect=true", but we feel that this could become a performance issue as this causes 2 requests from the browser each time.
On the other hand, I gave up trying to implement Seam security after getting so many missing dependencies errors.
The best solution I have found so far is a custom phase listener from Duncan Mills - Effective Page Authorization In JavaServer Faces, but I'm not 100% convinced this should be used on public facing JSF applications.
So finally, what does this leave us with ? I know this is a pretty wide open ended question, but I honestly have no clue where to go next. I'm pretty sure I have followed the different tutorials to the letter, for example Spring tutorials, but I'm still not satisfied with the way it works.
Could anyone at least confirm/infirm the fact that Spring security is supposed to work across JSF forwards, as I've seen many posts by others having the same issue ? That would at least give me a direction to keep going.
Thank you.
Combination of servlet filter for page validation (applied to the faces servlet), identity session bean (storing user attributes e.g. Role, login id) and a few methods for entitlement checks (e.g. isAdmin(), canViewRecord(recordID)) well ised throughout your page.
You see, when it comes to security I opt for not leaving it in anybody else's hand. also, I validate in several places (hiding a component won't keep folks from forging the right POST request to trigger specific bean methods so watch out).
When I work with JSF I use spring-security.
About the behavior that you comment that spring security allows redirections done with commands button, is weird you must have a wrong configuration because it seams working fine in my project (I just tested).
In any case you can also use the spring security tags to render or not components according to the user's role.
This is a project that can help you to implement the tags.
http://www.dominikdorn.com/facelets/
Hope this helps..
Related
Currently, I am working on a web project using JSF 2.0, Tomcat 7 and MongoDB. I have a big question of how to handle the session management and authentication/authorization with users in a database.
The structure I want is as follows: only logged in users can create events and everyone can see the created events.
create.xhtml --> only for logged in users.
events.xhtml --> public for everyone.
The basic structure I'm planning is:
Check if the page requires logged in user (e.g. create.xhtml)
If yes, check if user is logged in
If user is not logged in, go to login.xhtml
If successfully logged in, come back to requested page
Keep the "User is logged in" information unless user clicks log out
button. (there I guess #SessionScoped gets into play)
The question is:
What is the less complicated way of doing this?
Where should I use the #SessionScoped annotation? In Create.java or
LoginManager.java?
Spring security looks kind of complicated for my issue, do I really
need it? if yes, can you explain a little bit of how the implementation works together with JSF 2.0 and Mongo DB?
There are several options. Which to choose is fully up to you. Just objectively weigh the concrete advantages and disadvantages conform your own situation.
1. Use Java EE provided container managed authentication
Just declare a <security-constraint> in web.xml which refers a security realm which is configured in servletcontainer. You can for your webapp specify URL pattern(s) which should be checked for login and/or role(s), e.g. /secured/*, /app/*, /private/*, etc.
Before Java EE 8, you unfortunately still need to configure a security realm in a servletcontainer-specific way. It's usually described in servletconainer-specific documentation. In case of Tomcat 8, that's the Realm HOW-TO. For example, a database based realm based on users/roles tables is described in section "JDBCRealm".
Since Java EE 8, there will finally be a standard API based on JSR-375.
Advantages:
Relatively quick and easy to setup and use.
Since Java EE 8 there's finally a robust and flexible standard API.
Disadvantages:
Before Java EE 8, realm configuration is container-specific. In Java EE 8, the new JSR-375 Security Spec should solve that with help of JASPIC.
Before Java EE 8, , there is no fine grained control.
Before Java EE 8, it's very spartan; no "remember me", poor error handling, no permission based restriction.
See also:
Performing user authentication in Java EE / JSF using j_security_check - contains complete code examples
Java EE kickoff application - example web application (developed by me) which also demonstrates Java EE 8 authentication with Soteria (the JSR-375 RI).
2. Homegrow a servlet filter
This allows for much more fine grained control, but you're going to need to write all the code yourself and you should really know/understand how you should implement such a filter to avoid potential security holes. In JSF side, you could for example just put the logged-in user as a session attribute by sessionMap.put("user", user) and check in the filter if session.getAttribute("user") is not null.
Advantages:
Fine grained control.
Completely container independent.
Disadvantages:
Reinvention of the wheel; new features require a lot of code.
As starter, you're never sure if your code is 100% robust.
See also:
Is there any easy way to preprocess and redirect GET requests? - contains introducory explanation and kickoff example for authentication
Authorization redirect on session expiration does not work on submitting a JSF form, page stays the same - contains more extended kickoff example for authentication which also covers ajax requests
How control access and rights in JSF? - contains kickoff example for authorization
3. Adapt a 3rd party framework
For example, Apache Shiro, Spring Security, etc. This offers usually much more fine grained configuration options than standard container managed authentication and you don't need to write any code for this yourself, expect of the login page and some (XML) configuration of course.
Advantages:
Fine grained control.
Completely container independent.
No reinvention of the wheel; minimum of own code.
Thoroughly developed and tested by lot of users, so most likely 100% robust.
Disadvantages:
Some learning curve.
See also:
JSF2 - Shiro tutorial - an extensive tutorial on integrating Shiro in JSF2 webapp
I am trying to get into a big JSF application made by others with almost no documentation. I already got a general comprehension of the application architecture, and about what it should do from a functional point of view. But now I would like to understand what is the process in the code when I navigate in the application using my web browser.
I especially lack sequence diagrams that would show for a single story what code is called.
I tried using debug mode in eclipse and use break points to see what is called, but since a lot of code is called by the faces servlet, the step by step keeps returning into the JSF library and I am wasting a lot of time guessing what part of the code might be called next. I also look into the xhtml code to see what methods are called, but since each JSF page visible in the browser is made of a dozen of tiny xhtml fragments (using ui composition and custom components) it is quite easy to get lost.
So here is my question: Is there an easy way to associate a story from the browser point of view with the corresponding code in the backing beans?
Ok
I finally managed to get a better understanding of what was happening, thanks to all the comments on my questions, and to the facesTrace project, which was originally part of primefaces and aims to enhance the traceability of JavaServer Faces based applications. I found here how to configure it, and I adapted it a little to my project. Suprinsingly, it worked very well (the project is JSF 1.1). Then I wanted to get the logs working in FacesTrace. I found a hint there, but had to adapt a little because the package name of the Appender has changed.
I would have loved to give a few more links but Stackoverflow limits me to two links, hope those will stay alive forever.
To be fair, using a good old logger and a context listener would produce the same result, but what I appreciate is that it is well presented and I can reduce the scope of the log to the log of the request, even though I have some doubts of what would happens if several users were debugging at the same time since it uses log4J.
We are using JavaServer Faces 2.2 (Mojarra 2.2.1) in our project. I noticed something odd. On a page called reporting.xhtml where I use f:metadata with the new f:viewAction my browser, Safari in this case, shows the following query string:
reporting.jsf?jftfdi=&jffi=reporting%3Ffaces-redirect%3Dtrue
What wizardry is this? What are the parameters jftfdi and jiffi doing? What is their purpose?
It's part of the new JSF 2.2 feature as described by spec issue 949. Basically, it enables JSF to identify the client window. It's basically the same as cid in CDI's #ConversationScoped and windowId in CODI's #ViewScoped/#ViewAccessScoped. This client window ID is in turn used by among others the new JSF 2.2 #FlowScoped scope as described by spec issue 730.
The "What's new in JSF 2.2?" article of my fellow Arjan Tijms explains the need pretty clearly:
LifeCycle
Identify client windows via a Window Id
Arguably one of the biggest problems that has been plaguing web application development since its inception is the inability to distinguish requests originating from different windows of a single browser. Not only has an actual solution been long overdue, it has taken a long time to realize this even was a problem.
The root of the problem, as always, is that the HTTP protocol is inherently stateless while applications in general are not. There is the concept of a cookie though, which is overwhelmingly the mechanism used to distinguish requests from different users and to implement things like a session scope where on its turn the bulk of login mechanisms are based on.
While a cookie does work for this, it’s global per browser and domain. If a user opens multiple tabs or windows for the same domain then requests from those will all send the same cookie to the server. Logging in as a different user in a different window for the same website is thus not normally possible, and having workflows (involving post-backs, navigation) in different windows can also be troublesome because of this.
In JSF there are various solutions that are somehow related to this. The view scope effectively implements a session per window as long as the user stays on the same page and does only post-backs. The Flash is used for transferring data between different pages (presumably within the same window) when navigation is done via Redirect/GET. There’s a wide variety of scopes implemented by third parties that do something similar.
All of these have some implicit notion or assumption of the concept of a ‘client window’, but there is no explicit API for this.
JSF 2.2 will introduce support for two different aspects of this:
Identification of an individual window: the Client Window Id
API and life-cyle awareness of the window concept
Apparently you've configured your application as such.
See also:
What's new in JSF 2.2? - Lifecycle - Identify client windows via window Id
What's new in JSF 2.2? - Navigation - Faces Flow
I am trying to learn the concepts of Java EE (EJB,JSF...) and therefore I am working on an example application.
Unfortunately I have problems to understand how some concepts should work together and if I am doing it in an correct professional manner. At this point, I am really confused about all these different methods and hope someone can help me out.
The core functionality of my application consists of a document server where registered users can upload documents and describe it with useful information.
The Documents should simply be saved on the Server and all Information should be stored in a MySQL Database.
I created three Projects with Netbeans.
Enterprise Application Project (DocApp)
EJB Module (DocApp-ejb)
and a Web Application Project (DocApp-war).
The main things work fine like
accessing the database with JPA
uploading files with primefaces FileUploader
injecting JSF with EJB
and even the user authorization with JDBC-Realm as shown in this tutorial
http://jugojava.blogspot.de/2011/02/jdbc-security-realm-with-glassfish-and.html
My Problem now is, that all pages in a specific subdirectory should only be accessible by registered users.
The only way i see is to use one SessionScoped ManagedBean, instead of using multiple RequestScoped ManagedBeans .
This seems to be a bad practice but I have no Idea how to handle this otherwise.
The way i understand it, there should be one ManagedBeand for every JSF Page (xhtml).
Is there a good way to handle this or am i doing anything wrong?
The default mechanism to give access to a whole sub directory is adding a security constraint in web.xml for the URL pattern representing that directory.
Every registered user should get a role that represents being registered, eg "REGISTERED"
This role is then added to the security constraint in web.xml.
The interaction between JSF and the Servlet container managed security is a little awkward, but it does work.
I'm trying to use ace:fileEntry to upload a picture, as I read this component requires a submit from h:commandButton in order to start downloading. My problem is that when I switched my ice:commandButton with h:, my managed bean (which is in Conversation Scope) gets created again (#PostConstruct called) and the method in h:commandButton and also the fileEntryListener aren't called anymore.
And as another problem that might be causing this is that when I first enter my page the managed bean gets created and I call conversation begin, but when I do a second request (from a commandLink) the managed bean is created again, and a new conversation is started, after that you can play how long do you want the managed bean doesn't get created again.
Back to my initial question, if I have ice:commandButton the managed bean ins't created again, if it's with h: it gets created again.
And to add a little bit more fun in it, if I remove the rendered attribute (which resolves to true) from ace:fileEntry the fileEntryListener is called, but the action from h:commandButton isn't called no matter what.
I tried to add explicit ids to the components, tried to change ice:form with h:form .. nothing. Please Help.
Ps: why ICEfaces 2 can't work with all ice components, why does it requires h:commandButton, instead of ice:commandButton, why the new JSF 2.0 stuff with f:selectItems backed by a regular list isn't working with ice:selectOneMenu, works just with h:selectOneMenu ? What's up with ICEfaces ? And why CDI doesn't work as expected, with Seam 2 also I had problems with conversations called twice .. ps2: if I don't navigate to another view ?cid=1 isn't present in the URL.
Now, with ace:fileEntry and h:commandButton, the reason why the ice:commandButton can not be used is because that is an AJAX component, and browsers will not upload files in an AJAX submit. Even with HTML5 it is not automatic, and new File and XmlHttpRequest APIs must be used. In an HTML4 browser, only a full page, full form, submit will upload the file contents, and only h:commandButton operates that way. For more details, you can see this explained near the top of the page at:
http://wiki.icefaces.org/display/ICE/FileEntry
With our ice: components, which are extended variants of the h: components, such as ice:selectOneMenu, they are lacking some new JSF 2 features because we have been focusing on our newer Advanced Component Environment, due to customer demand for rich client-side components. As well, the focus was on maintaining backwards compatibility with the ice: components, to ease customer migration from ICEfaces 1.8.x to ICEfaces 2.x, and less so to be altering those components' behaviours. But we are still actively maintaining and improving the ice: components, and will be adding the new features soon. Feel free to create any enhancement requests in our Jira system, and to vote on any existing entries, as this does guide our development priorities.
http://jira.icefaces.org/
Mark Collette
I'm Mark Collette from the ICEfaces component team, and hopefully I can answer some of your questions.
Most of your issues seem more related to CDI integration than problems with the components themselves. I know that the symptoms change depending on which component you use, but I think that's because the ice: components use AJAX and the h: components do not. Many times integration issues with other frameworks are more observable in AJAX interactions than in full page GET/POST interactions. So your issues may be due to either our CDI integration, or your application's configuration. So please review our documentation on using ICEfaces with CDI, and if you you still experience any issues, I recommend posting the details to our forums.
http://wiki.icefaces.org/display/ICE/Using+ICEfaces+with+CDI
http://www.icefaces.org/JForum/forums/list.page
[Sorry, but this forum is not letting me post more than 2 links, so I'll split the rest of my message into another post, and hopefully that will work]
Mark Collette