Reputation: 933
I'm using Shiro
in a JSF
application and look for guidance on how to handle user attributes like: Id (from the database), email etc. as part of the information held by the Shiro Subject
.
Having read the Shiro
manual, it seems to me that there's no reason for me to have a SessionScoped
bean to hold the user information, as I already have the Subject
. The question is how to best store the user information that is not part of the Subject
by default.
I've seen different examples where some use Principals
and other put a separate custom made User
object in the current Session
like:
User user = userDAO.findByName(user.getUsername());
subject.getSession().setAttribute("user", user);
It would be elegant to get hold of - for example - the user id like this:
userId = subject.getUserId();
or email:
email = subject.getEmail();
But I guess that is not likely to be possible - so my question is: What is best practice for this? And I'd also like to ask: is there any good reason to keep a separate SessionScoped
bean alive for the purpose of user sessions?
Upvotes: 0
Views: 626
Reputation: 1009
For my understanding the principal is the pure object for identification, authentication or remember me function. So put additional info to session (setAttribute).
When a user logs in, load the data and put it to the session with setAttribute. Or when a user comes back with remember me, use the principal to identify the user, and load the necessary things back to session.
It's up to you to decide how much data you want to hold in session for every user. If you want to keep memory consumption small on server, just store data to identify the user (maybe it's already in the principal) and load the data when needed in every function. This way is typically more cpu and database heavy. If you don't have that much users, just put it to session and make your life easier.
// Do login
Subject currentUser = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(email, password);
currentUser.login(token);
// load attribues
Long uuid = (Long) currentUser.getPrincipal();
Long ucid = // load other ids;
String email = // maybe load email and other stuff
// set attributes
currentUser.getSession().setAttribute("UUID", uuid);
currentUser.getSession().setAttribute("UCID", ucid);
currentUser.getSession().setAttribute("EMAIL", email);
...
// some function
public void doSomething() {
Long ucid = (Long)SecurityUtils.getSubject().getSession().getAttribute("UCID");
// do something
}
In my example, my principal is just the Unique User Id. That's enough to identify every user. Some Users are also customers, so i save this id too (saves me database access everytime). You can also save more stuff like email or whatever you need.
I duplicated the UUID from the principal to the session, just for comfort. I don't like mixing up principal casts and session access. This keeps my code clean.
Upvotes: 0