First off, I understand that the view of the Shiro developers is that remember me is not typically a good idea from a security standpoint.
That said, I'm using the remember me functionality. :)
Upon successful login (not remember me), my app stores some data in the HttpSession. This data is required later for app pages to load properly.
I'd like to have this data stored in the HttpSession upon successful remember me authentication as well, but I can't seem to find a callout to do it with. I'm not sure if I'm missing it or not, but ideally it would be a method that is called once when the remember me authentication happens.
For the time being I've overridden AbstractRememberMeManager.getRememberedPrincipals() with something like this (pseudo):
On Mon, Feb 22, 2010 at 12:17 AM, Jon Chase <[hidden email]> wrote:
> First off, I understand that the view of the Shiro developers is that
> remember me is not typically a good idea from a security standpoint.
> That said, I'm using the remember me functionality. :)
Actually, its not bad to use RememberMe - it is a nice feature. But
RememberMe does not represent an *authenticated* user, so we need to
make that distinction so Shiro users can make decisions accordingly.
> Upon successful login (not remember me), my app stores some data in the
> HttpSession. This data is required later for app pages to load properly.
Shiro stores an encrypted version of the PrincipalCollection in the
remember me cookie. Can you store that data as principals in the
collection? If so, that data will be automatically saved and
available when the identity is retrieved. Then you could retrieve it
later from subject.getPrincipals(); This is why there can be multiple
principals other than just the application's unique identifier.
But you're right, this process occurs on every request until the user
is properly authenticated and so it might not be the most efficient
mechanism - it might be good to provide a callback or event to react
to this. Could you please open a Jira feature request if you'd like
In the meantime, the best place for logic like this is probably the
SubjectFactory implementation - you're basically editing Subject state
based on when the instance is created. You'll probably want to
subclass DefaultSubjectFactory or DefaultWebSubjectFactory depending
on your environment.
Let us know if this is ok or if you have other ideas that might better
reflect your environment - we're certainly open.
I have the same requirements. I am trying to use a custom security manager that extends from DefaultSecurityManager and a custom rememberMe manager that extends from CookieRememberMeManager. In my custom class, I override onSuccessfulLogin and rememberMeSuccessfulLogin to provide my own after-login hook:
In my case, whenever a remember me logon occurs, I wish to invoke some code, let's say foo(subject), which is passed the Subject. What I think I really want is that a onSuccessfulRememberMeLogin() method be part of the CookieRememberMeManger class, and that it would be called when a remember me cookie is authenticated and would be called only once. (I know that there is a onSuccessfulLogon() method but it is called whenever any logon is successful.)
(When a regular login is successful, I call onSuccessfulLogin() in my FormAuthenticationFilter-extended class which then invokes my app-specific code, foo(subject) to do some setup.)
I can't hook into getRememberedPrincipals() because the Subject hasn't been created at this point. I thought that perhaps in SecurityManager, I could hook into createSubject() but this method might be called from other places.
Just a follow-up. I was able to resolve this issue by extending DefaultWebSecurityManager and overriding createSubject(SubjectContext subjectContext). It now has almost the same functionality but allows a callout to a new method to handle my application-specific initialization for remember me sessions.
The key change in createSubject() were these lines:
final boolean before = context.getPrincipals() == null;
context = resolvePrincipals(context);
Subject subject = doCreateSubject(context);
if (before && context.getPrincipals() != null)
Object o = context.getPrincipals().getPrimaryPrincipal();
if (o instanceof String)
onSuccessfulRememberMeLogin(subject, (String) o);