• Post Reply Bookmark Topic Watch Topic
  • New Topic

User in many roles

 
michal stankiewicz
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi guys,
This is my first post on that forum, so I say hi :P

I want to make user authentification. In my authentification, user gives his password and login and if it is correct he is logged. It sounds simple. But what I want to do, is to restrict his access to some parts of service based on group he belong to. Sounds normal too.
But the problem is, I want to be there many groups, every groups has its name, description and roles it is assigned to. Roles and groups are many-to-many relationship, so basicly, user <-> role is many to many relationship. How to do that kind of authentification, that user will belong to many roles.

Lets say I will be using Java 1.8. Java EE 7, JavaServer Faces, Glassfish server with realm authentification and mysql database.

I have read, you can do it using multi realm authentification or using method isUserInRole, but no idea how to use it. Moreover, as I have read, JDBC realm will see only one role per one user.

Correct me if I am wrong, and move thread if it is not in correct section.
 
Tim Holloway
Bartender
Posts: 18412
58
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi right back, Michal! :) Welcome to the JavaRanch!

It is perfectly acceptable for a user to have more than one security role granted to him/her/whatever. This is very convenient in that, for example, a person in the "employee" role could be granted also the "manager" role while the boss is on vacation, then when the boss returns, the security administrator simply deletes the database record pairing that person's ID with the "manager" role id.

It is not true that the JDBC realm allows only one role per user. The effective implementation of the isUserInRole() method is as follows:


This is the effective code - the actual code is more complicated (plus I forget if a preparedStatement query truly returns the number of records or if in the real world you have to ask the statement itself.

Note that like all good security, the query doesn't actually fetch the role record because that exposes data. Instead it merely asks if it exists.

One VERY thing to remember when using container security in JSF. The security system maps against the incoming URL. Since JSF URLs often lag behind what you're actually accessing, secured requests should navigate using the "REDIRECT" option. That will force the URLs to track properly at the expense of a small overhead.
 
michal stankiewicz
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So i can just have table
users ( username VARCHAR(32) PRIMARY KEY, passwd VARCHAR(32) NOT NULL, ...)
roles ( rolename VARCHAR(32) PRIMARY KEY, ...)
roles_users ( username VARCHAR(32) REFERENCES users(username), rolename VARCHAR(32) REFERENCES roles(rolename), ...)
and view
v_roles_users ( username VARCHAR(32), passwd VARCHAR(32), rolename VARCHAR(32))

give it to JDBC realm on glassfish server, and he will get it, i mean view,

than in program how do I get access? Will normall javax.annotation.security.RollesAllowed work? Will he see all roles? Or do I need servlet for each access, there check if user is in role, if yes redirect to page he want, if not redirect to page "access denied"? If I need to make servlet, how do I do redirection, so primefaces will work

One more question. Any tutorial on how to do unit test in java ee / or other tests
 
Tim Holloway
Bartender
Posts: 18412
58
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Actually, you only need the users (userid/password) and roles_users (userid/roleid) tables. The JDBC Realm doesn't use anything more.

There is no mechanism whereby the appplication can enumerate what roles a user has. That violates the "don't volunteer" axiom of good security I mentioned previously. All you can do is ask IF the user is in a role, either directly (request.isUserInRole()) or as part of a URL security mapping in web.xml.

You would not write servlets to invoke usUserInRole(), you'd do that from the property and action methods. Since getting to the actual is UserInRole() method in a JSF app is messy and requires platform-dependent code, I use a service class to abstract that part out (this also aids unit testing).

So, for example:


The Struts framework allowed role-checking on the View tags, but stock JSF does not (some extension may, however). So the alternative is to fake it:




In the real world, I usually define my roles as manifest constants and I may abstract things further, but this is the basic idea.
 
Tim Holloway
Bartender
Posts: 18412
58
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Incidentally, if you'll ask about testing as a separate topic, I'll discuss it there. Making it a new topic helps other people find it easier and keeps questions on one subject from getting muddled by answers on another subject.

Also, I'm not sure that the @RolesAllowed annotation works with JSF. It's primarily for stuff like EJBs where methods are secured on a per-method basis and that doesn't fit as easily to JSF backing bean methods.
 
michal stankiewicz
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok so I will ask in other topic.
This is my glassfish-web.xml file. Is it correct? I have a problem now -> #{request.remoteUser} returns correct user, but #{request.isUserInRole('admin')} returns always false
I am using glassfish 4.1, JavaServer Faces 2.2, Primefaces 5, Java 8, Java EE 7


and this is my web.xml file



and i have a login bean like that:


How can i make a bean like that disapper if I remove history with coockies? Od do I need to check it every time, if difference had been made?
 
michal stankiewicz
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Do not see anymore edit button, I changed web.xml adding



 
Tim Holloway
Bartender
Posts: 18412
58
Android Eclipse IDE Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Try and keep your examples short. It's easier to read them that way, and when you get free help you have to expect that there's a limit to how hard people will work.

One thing that really puzzles me is your "setRoles" function. The JEE security framework does not assume that the Realm has a databse behind it. I've written Realm modules for web services, and my standard site security on my own server farm isn't database-based, it's LDAP-based. So right off, you're violating the write-once/run-anywhere aspect of JEE security.

Also, more practically, it's common for the authentication mechanism to cache information. Changes to a user's role set usually requires that the user must log out and log back in again before the new roles take effect. In fact, it may be mandatory, since changing a user's role set in the middle of a session is an opportunity for security exploits where an unfriendly agent might be able to catch the user with parts of both role sets in effect at the same time. Recall that JEE is multi-threaded.

This EL expression offends me:


1. It tightens coupling by explictly requiring an HTTP interface to work (JSF was conceived as an abstract MVC framework. HTTP is just the standard transport).

1a. It also tightens coupling by requiring the View to explicitly know what the literal values of the role names are.

2. It puts what is effectively server-side code on the client-side View definition. Which doesn't always do what you think it will do.

3. EL should be kept as simple as possible if for no other reason than it is hard to get a debugger to work with it.

That's why my example had a property method to do role-checking.
 
michal stankiewicz
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tim Holloway wrote:
This EL expression offends me:

.

Can I at least use #{request.isUserInRole('admin')} to render menu elements in template? Set roles has been removed from LoginBean, out of sense that was.

Do you know how to insert/update/delete recods in join table if I want to only use auto-generated persistance macanism I get from "create entity classes ..." and "create jsp pages ..." ?
 
Tim Holloway
Bartender
Posts: 18412
58
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I really don't recommend coding any more complexity in EL than is absolutely necessary. And, as I said, by using a "magic constant" value in your View Template, you've coupled your View and Model environments more tightly than necessary.

The biggest problem with having code spill into the View is that there's not longer any one indisputable place to find out where things are being done. You have to go on a "treasure hunt" to find out and you may have to juggle multiple objects to make sense of things.

JSF does not concern itself with persistency, so the mechanisms you employ would be the same ones that work for non-web applications.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!