I am using Java EE 6 with all reference implementations. Having made some security constraints for some pages such as everything beneath /secure/*
. This is rough grained security. What if two users both have the same roles, but some content of the same page should only be visible to user "John" for example? Or a totally different page should be shown to "John"? I have many questions un-answered around this so it would be nice if somebody could provide some links/explanations or books that cover this as well. I need more fine grained security control.

- 17,424
- 4
- 58
- 94

- 47,771
- 85
- 270
- 434
-
Do I read the comments right that the bounty is already promised? – Matt Handy Apr 17 '12 at 06:32
-
@MattHandy I give the bounty with the best answer. I am very interested in how to do more fine grained security particular in JSF, like how you hide things from people that not has a particular role, identity etc. Also how you do it back end. – LuckyLuke Apr 17 '12 at 10:07
-
Please read through the hour long discussion Viper and I had where I explained a number of things. – Anonymoose Apr 18 '12 at 01:28
-
Have you considered an external module/framework (e.g., Spring Security) or is that not an option? – quantum Apr 18 '12 at 20:33
4 Answers
The fine-grained security features you're hoping for not only exist, Oracle even has a useful blog post covering the subject in detail, complete with sample code.
And because it would be terse and impolite of me to simply link the docs and run, what follows is a bit of discussion on how this goes together to the best of my understanding.
The 0th problem: rough-grained, declarative security
The biggest problem with declarative security is it forces you to iteratively define all of your user roles at design time. This is extremely undesirable for two reasons: first, it fails to properly abstract your security model away from your implementation (failing to adequately future-proof your application and opening the door to information disclosure vulnerabilities), and second, it tethers your user roles to the immediate design of your application, routinely failing to provide fine-grained permissions or ACLs when they're desired or necessary.
In effect, this is a problem of insufficient abstraction. You're using a system that immediately meets your current needs, but not one that you can expect to be workable or maintainable over the life cycle of your application, as roles become more complex and the complexity of your code base steadily increases.
Fine-grained security using Managed Beans
The first-order solution here is to use an abstraction model that allows you to define user roles independently in the context of each JSF method call, allowing you to swap them in or out as needed. As a bonus, this allows you to define finer-grained permissions, as such a scheme allows you to define your permissions per method instead of per view, per endpoint, or per bean. And if the roles change? You only need to update your permissions model in a single location, instead of going to each of those beans and swapping out their user definitions.
The aforelinked article goes into far more detail than I'm willing to cover here, so I highly recommend reading the blog post. But the takeaway here is, to do this properly, you should provide both an authentication stack and an annotation layer detailing permission roles, and the twain shall only meet where you've explicitly and deliberately connected the two.
Defining fine-grained method calls and a security policy that makes sense is left as an exercise for the reader, but if you have questions in this area, feel free to ask them in the comments or in a set of follow-up questions, as these questions are inherently useful to a wide audience.
Improvements
It's conceivable that this solution isn't robust enough for your needs. For example, if you wish to authenticate users using LDAP or Kerberos to provide a unified representation of your users and roles, this only provides a partial solution to meet your needs. Several great resources exist in this domain, but this is otherwise left as an exercise for the reader.
The ultimate takeaway here is, in the perfect world, this is how your application security should be defined. Your needs may vary, and for something left at the small scale, simple, declarative security may be fine to meet your needs. After all, that's why it continues to exist.
But, for larger applications that must meet the needs of a large number of users securely and correctly, this is the right way to go. It requires a bit more knowledge and overhead, but it'll save you copious amounts of time, effort, and frustration if you begin by doing it properly.
As always, best of luck with your application.
The simplest approach is
<h:panelGroup rendered="#{request.userPrincipal.name == 'user1'}">
<p>Content for user 1</p>
</h:panelGroup>
<h:panelGroup rendered="#{request.userPrincipal.name == 'user2'}">
<p>Content for user 2</p>
</h:panelGroup>

- 5,662
- 4
- 33
- 41
-
1What about this: I have a page named `profile.xhtml` and a request parameter named `username`. If a user goes to `profile.xhtml?username=Amanda` and is not logged in as Amanda he/she will get a limited view of the profile. Now, would you do it? Having these checks around in the view code or can you give that user another view? Like you have two profile.xhtml pages. Or...do you make a profile.xhtml page and then you use Facelets tags (composition) and include the content of the profile view based on what the user is logged in as? What are the options for solving such cases? – LuckyLuke Apr 14 '12 at 20:09
-
This is one reason Facelets is not to my taste. Conflating view concerns with controller concerns makes easy things easy and intermediate things very hard. I would probably end up with the two pages glued together as one facelet, each part guarded by a rendered attribute. Anyone have a better approach? – Anonymoose Apr 14 '12 at 20:14
-
Are there alternatives? Also when using Container managed security I log in with the for and posting to j_security. Where would you initialize a "UserBean" that holds the information about the currently logged in user? – LuckyLuke Apr 14 '12 at 20:15
-
1Just inject a UserPrincipal into your bean. It's magic! All this authentication/authorization business is handled for you by the container. – Anonymoose Apr 14 '12 at 20:17
-
How would you hide certain links etc from a view if a user is not logged in? Or have the right role? – LuckyLuke Apr 14 '12 at 20:19
-
-
No, because I give 450 reps to the guy with the best answer on how to do more fine grained security in JSF? May you come on Java chat for a bit? – LuckyLuke Apr 14 '12 at 20:24
-
let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/10085/discussion-between-anonymoose-and-viper) – Anonymoose Apr 14 '12 at 20:25
Showing multiple versions of the same page is not about security (different version != links hiding), restricting access and requiring additional authorization is, I'll answer that if you dont mind.
You can read about both (authentication, authorization) on JAAS page. It is also the best framework in my opinion. It takes some time to master but after then, it's pretty easy and you'll even realize it's not heavy-weight at all - you're not forced to use every single feature. (just like EJB)
JAAS can log you even using ldap or windows account, theres even support for multiple authentication steps - you can implement pass+sms login. You can do that even with acegi, of course (it's just not that easy)
Since you've already mentioned JSF, JAAS fits even better than acegi, you can annotate any backing bean with @RolesAllowed and if user session does not meet requirements, SecurityException will be thrown. This works for servlets and beans (ejb, backing), not for jsps (however it wouldnt make much sense anyway)
You can read about @RolesAllowed here, but if you're already considering it, don't miss JBoss Seam Security - it's built on top of both security annotations and JAAS and it's also pretty addictive to use. Worth of reading.
BTW guys: I'm not rep-whoring, just found interesting question so... feel free to fight for bounty :)

- 2,415
- 2
- 28
- 32
Usually this kind of content will be held in the session variables. So you do not have to think about what user is logged in.

- 1,530
- 1
- 13
- 15