4

I use Shiro 1.2.3 in a JSF2 project. I couldn't find a way to update the principal of an authenticated subject without a logout. I need this when a logged-in user wants to update his/her profile info. I store a userBean as principal and it should be updated along with the profile info. Doing a programmatically login can be a solution but this time password of the user is needed to create a token.

K C
  • 41
  • 3
  • 1
    Why you want to change the user principal. It is the key that is used for all authorization and authentication that he has been allowed after login. In general Principal is the userid of the user. If you change it between then it may show inconsistent behaviour. Also as per standard principal is a userid and should not be changed so that you can track it in history data. If you need some thing changed it might be physical name of user. – Dev Jul 30 '15 at 04:19
  • 1
    @dev You can set any object as a principal (even multiple). Performance wise it is suggested to store only a unique id however. In my app i set a lightweight User class (has userId, username, email, firstname and lastname properties) as principal because i display each field very often by using `` tag. – K C Jul 30 '15 at 13:59

1 Answers1

2

Some time has past but I hope this could be useful to others too.

When you login with Shiro a Session is created and a token is sent to the client for further requests.

For each request Shiro intercept the HTTP request, verifies the token as valid then creates a new Subject using the org.apache.shiro.web.mgt.DefaultWebSubjectFactory.createSubject(SubjectContext context) method which contains an important line

PrincipalCollection principals = wsc.resolvePrincipals();

which finally bring us to the solution method org.apache.shiro.subject.support.DefaultSubjectContext.resolvePrincipals() which contains the critical lines

Session session = resolveSession();
if (session != null) {
    principals = (PrincipalCollection) session.getAttribute(PRINCIPALS_SESSION_KEY);
}

That is to update your Subject's Principal without logout you need to update his/her session's PRINCIPALS_SESSION_KEY attribute. To summarize your code could be as simple as

PrincipalCollection pc = (PrincipalCollection) getSubject().getSession().getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY;
// do something in here   
getSubject().getSession().setAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY, pc);
user2688838
  • 761
  • 5
  • 11