You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@shiro.apache.org by Tauren Mills <ta...@tauren.com> on 2010/05/11 18:22:30 UTC

Re: Keeping track of user's last login date

I'm just getting back to this issue now, and have updated to the latest
shiro snapshot.

When I started working on this, I had extended WebRememberMeManager, but it
looks like it is now depricated. What is the recommended approach at this
time? Should I be directly extending AbstractRememberMeManager?

I also wanted to point out that your example in this thread shows passing a
Map to getRememberedPrincipals, but in my experience I had to pass a
SubjectContext.  Before I proceed further, I just want to make sure that I'm
heading down the proper path that will be supported in the future, and not
implement something that I'll have to change later.

Thanks!
Tauren







On Mon, Apr 19, 2010 at 12:14 PM, Les Hazlewood <lh...@apache.org>wrote:

> I committed a change to how cryptography works on Friday - that might
> have done something with it (we encrypt principals by default).
> However, all the test cases still passed and I know that we do have
> some test cases around remember me cookies (WebRememberMeManagerTest).
>
> Please open a Jira issue in the mean time so we don't lose it.  I'll
> try to run the sample web app(s) to see if they exhibit the same
> behavior.
>
> Thanks!
>
> Les
>
> On Mon, Apr 19, 2010 at 10:57 AM, Tauren Mills <yo...@gmail.com> wrote:
> > It seems that my remember me function got broken at some point. All of my
> > requests do not have the cookie they used to. I've tried logging off and
> > back in again, but still no cookie.  This is
> causing getRememberedPrincipals
> > to run with every single request. Obviously not good.
> > Any suggestions on how to track down where the remember me problem is
> coming
> > from - why I'm not getting cookies? I haven't done much of anything with
> > Shiro for months now, and it used to work, so not sure what happened. Was
> it
> > broken in some recent release that I may be using?
> > Thanks,
> > Tauren
> > On Mon, Apr 19, 2010 at 3:41 AM, Tauren Mills <yo...@gmail.com>
> wrote:
> >>
> >> Les,
> >> Thanks, I'll look into doing this. Are there any examples of using an
> >> AuthenticationListener that I could reference?
> >>
> >> Tauren
> >>
> >> On Fri, Apr 16, 2010 at 9:10 AM, Les Hazlewood <lh...@apache.org>
> >> wrote:
> >>>
> >>> Hi Tauren,
> >>>
> >>> You could implement an AuthenticationListener - I typically like to do
> >>> this for these kinds of operations.
> >>>
> >>> Since Shiro does not count remember me as a true authentication, the
> >>> AuthenticationListener will not be triggered for remember me events.
> >>> To do that you would also need to implement your own
> >>> RememberMeManager.  Typically subclassing the default one and updating
> >>> the timestamp in the getRememberedPrincipals method would work:
> >>>
> >>> @Override
> >>> public PrincipalCollection getRememberedPrincipals(Map subjectContext)
> {
> >>>    PrincipalCollection principals =
> >>> super.getRememberedPrincipals(subjectContext);
> >>>    if ( principals != null ) {
> >>>        int userId = principals.getPrimaryPrincipal();
> >>>        //update the last login timestamp for user with this id here
> >>>    }
> >>> }
> >>>
> >>> The above method is called only if the current Subject/session does
> >>> not yet have an identity associated with it.
> >>>
> >>> The AuthenticationListener + the above overridden method should do it!
> >>>
> >>> Cheers,
> >>>
> >>> Les
> >>>
> >>> On Thu, Apr 15, 2010 at 8:37 PM, Tauren Mills <ta...@groovee.com>
> wrote:
> >>> > What would be the best way to update properties of a member on
> >>> > successful
> >>> > authentication? Basically, there is a Member.lastLogin property that
> I
> >>> > want
> >>> > updated with the current date every time a member comes back to a
> site
> >>> > and
> >>> > logs in.  However, this should also support rememberme
> >>> > authentications. I
> >>> > don't necessarily want to update the lastLogin property on every
> single
> >>> > interaction the user has on the site, just once for each session.
> >>> > Is there some technique in Shiro to do this, a callback of some sort,
> >>> > or
> >>> > some other method? Or should I be doing this in my application?
> >>> > Also, I can't seem to view much of the documentation. All the links
> on
> >>> > the
> >>> > following page require an Apache login. Is it supposed to be this
> way?
> >>> > http://incubator.apache.org/shiro/core.html
> >>> > Thanks!
> >>> > Tauren
> >>> >
> >>> >
> >>
> >
> >
>

Re: Keeping track of user's last login date

Posted by Les Hazlewood <lh...@apache.org>.
Hi Tauren,

I'll answer in-line:

> Thanks, I appreciate your very detailed response. So far, I've not used
> native sessions and have been using http sessions. But I'm intrigued by
> using shiro sessions instead. I'm afraid I may be a little brain dead right
> now, as I'm not quite understanding the issue with native sessions.
> Hopefully you can clear this up.

'native' sessions are Sessions managed entirely by Shiro - no servlet
container or EJB container needed.  They allow you to do things like
listening for session events and ultimately, control over how your
sessions are persisted.

Shiro in a web app will default to using the Servlet Container's
HttpSession to support all of the Subject.getSession() calls and
Session interaction.  But, if you use the native sessions, Shiro
bypasses the servlet container to manage Session lifecycles and access
itself, but of course fully implements the Servlet specification for
sessions to guarantee that you have the same session experience.

So you would use native sessions if you

1) want the extra features it affords you (SessionListeners,
SessionDAO to query sessions, e.g. "how many users are currently
logged in?)
2) want clients to share a session - for example, if you log in to a
web app and then launch a desktop application, your desktop
application can share session state with your web session.

> 1. So, with native sessions, it sounds like you saying there is no way to
> update my user data (via hibernate) until the user logs out or the native
> session expires. But SessionListener has an onStart(), so why would I not be
> able to?

Because when a session is started, it has no identity data associated
with it.  Your onStart implementation will always give you a session
that hasn't yet been associated with a user.  After a remember me data
is acquired, we can put it in to the session, but obviously a session
has to be started before we could call setAttribute to do that.

Now we could add a new listener mechanism that is triggered when a
user is associated with a session, but that would be a new feature -
please feel free to add a Jira issue to track this if you'd like it.

> 2. Are there other drawbacks to using native instead of http?

A little more configuration - you'll need to specify a reasonable
SessionDAO implementation to tell Shiro how to persist/acquire your
Session objects.  Most people use a nice enterprise caching framework
with disk overflow (important!) such as Ehcache, Coherence, etc.
Shiro has a org.apache.shiro.cache.ehcache.EhCacheManager that you can
use for this purpose.  The 'spring' sample application now uses it in
the SecurityManager configuration - you can use that as a starting
point.  When using native sessions, you'll also probably want to use a
org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO instance
and inject that into the SessionManager.

There, that's about it.  That's the additional configuration that
makes this the only 'drawback' that I can see.  I've been using native
sessions in my applications for a long time (years), so you shouldn't
have any problems.

> 3. Are there significant advantages to using native instead of http?

1) SessionListener support
2) Enterprise session clusters - a big deal IMO.  Coupled with an
enterprise caching framework (Ehcache+Terracotta), you can have a
beautiful fault-tolerant session cluster with no fear of losing
sessions if a web server crashes.  You're also not forced to use
sticky sessions since any machine in the session cluster could service
session requests (sticky sessions is still a good idea for performance
- data locality, etc - but not strictly required).
3) Your sessionDAO implementation can back to a datastore that
supports queries such as a NoSQL engine (simple queries) or
cache+hibernate for complex queries.  You'll be able to query for
information like:  "Is user X currently logged in?", or "How many
users are currently using the system?"  "How many guests vs
authenticated/remembered users do I have".  If you correlate sessions
to events or log entries, you can then use that information for very
valuable trend analysis ("What are my users doing during their
sessions?  How long do they interact with the application before they
leave it?").

There are a lot of other goodies, but those are the big ones.  This is
much easier to do IMO than, say, setting up Tomcat clustering because
you set it up with your configuration mechanism of choice - Spring
XML, INI, whatever.

> For now, I can certainly change my ShiroFilter so it doesn't include my
> static resources. Even if the user record gets updates a couple times when a
> session is created, it will be more acceptable.
> Thanks again for all the assistance, and for the great security framework!

Glad to help!  Thanks for being an early adopter and helping us make a
better framework :)

Best,

Les

Re: Keeping track of user's last login date

Posted by Tauren Mills <ta...@tauren.com>.
Les,

I just posted another related question to the list that explains my scenario
better. I decided to keep it out of this thread since it was really a
separate issue, but it relates to this thread, so might be good to reference
it.

Thanks, I appreciate your very detailed response. So far, I've not used
native sessions and have been using http sessions. But I'm intrigued by
using shiro sessions instead. I'm afraid I may be a little brain dead right
now, as I'm not quite understanding the issue with native sessions.
Hopefully you can clear this up.

1. So, with native sessions, it sounds like you saying there is no way to
update my user data (via hibernate) until the user logs out or the native
session expires. But SessionListener has an onStart(), so why would I not be
able to?

2. Are there other drawbacks to using native instead of http?

3. Are there significant advantages to using native instead of http?

For now, I can certainly change my ShiroFilter so it doesn't include my
static resources. Even if the user record gets updates a couple times when a
session is created, it will be more acceptable.

Thanks again for all the assistance, and for the great security framework!

Tauren




On Wed, May 12, 2010 at 12:03 PM, Les Hazlewood <lh...@apache.org>wrote:

> Hi Tauren,
>
> You discovered an interesting scenario.  Yes, it makes sense that the
> RememberMeManager would be consulted frequently if there are many
> different anonymous requests to the application, such as when a user
> with new session visits a home page which happens to have many
> resources (images, css, etc).
>
> But, the SecurityManager implementation should not continually
> reference the RememberMeManager once the identity is discovered - they
> are already 'remembered' at that point and there is no point in
> continuing to discover the identity.
>
> I've created a Jira issue to represent this:
>
> https://issues.apache.org/jira/browse/SHIRO-157
>
> And I'll work on it right away - it is definitely important enough to
> make it into 1.0.
>
> But realize that if a user with a new session visits a web page that
> requires many requests and those requests are filtered by the
> ShiroFilter (such as images, CSS, etc) you will have a race condition
> - some requests attempt to be resolving the identity at the same time
> and trying to update the session with the remembered identity.  Once
> any one of them updates the session, all other subsequent requests
> won't go through the rememberMe process.
>
> This is not critical really - you just might have one or two requests
> do unnecessary work.  Just be aware that your
> memberService.updateAccess could get called a small number of times
> before stopping for that user.
>
> So, there are two ways that I can think of off the top of my head to
> reduce or eliminate this problem:
>
> 1.  Don't have the ShiroFilter filter URLs that you don't think need
> security access/user association.  I typically do not have static
> assets (images, CSS, JavaScript, etc) filtered by Shiro since I
> usually don't find it necessary to secure these.  But, everyone has
> different requirements, so I'll leave that up to you.
>
> 2.  Honestly the best way I can think do this is via a SessionListener
> (this requires using 'native' sessions).  When the session stops or
> expires, the SessionListener can pull the user identity from the
> session and then update the member access time based on that identity.
>  Most people use the session's lastAccessTime property for this.  It
> is also cleaner in that you can implement a Listener intended for this
> type of behavior rather than having to subclass a Shiro implementation
> class.  But the one caveat here is that you can't update that
> timestamp at the moment their identity is discovered.  But in
> practice, most people don't care about that usually, but again,
> requirements differ.
>
> Does that help?
>
> Les
>
> On Wed, May 12, 2010 at 9:49 AM, Tauren Mills <ta...@tauren.com> wrote:
> > Les,
> > Thanks for the help.  However, now I'm having a problem
> > with getRememberedPrincipals() being called dozens of times per page
> > view, causing my "accessed" property to be updated many times, which is
> > obviously not ideal.
> > I believe this is because my application is running in Jetty, so every
> > image, JS, CSS, and other resource is causing a request to be created. My
> > cookie is set to / since I need it to work for many different paths.
> > Any suggestions on how to only update my "accessed" property a single
> time
> > per session?  I don't need the property updated with every request, just
> > when they first access the site for a session is fine.  Basically, the
> > property I currently called "accessed" would actually be more accurately
> > called "lastLogin".
> > Below is code if it helps.
> > Thanks,
> > Tauren
> > ---
> > public class MyRememberMeManager extends CookieRememberMeManager {
> > private MemberService memberService;
> >     @Autowired
> > public void setMemberService(MemberService memberService) {
> > this.memberService = memberService;
> > }
> > @Override
> > public PrincipalCollection getRememberedPrincipals(SubjectContext
> > subjectContext) {
> > PrincipalCollection principals =
> > super.getRememberedPrincipals(subjectContext);
> > if ( principals != null ) {
> > Long id = (Long) principals.getPrimaryPrincipal();
> > memberService.updateAccessed(id);
> > }
> > return principals;
> > }
> > }
> > // MemberServiceImpl.java
> > public void updateAccessed(Long id) {
> > updateAccessed(findById(id));
> > }
> > public void updateAccessed(Member member) {
> > member.setAccessed(new Date());
> > memberDao.save(member);
> > }
> >
> > // Spring config
> >     <bean id="securityManager"
> > class="org.apache.shiro.web.DefaultWebSecurityManager">
> >       property instead. -->
> >         <property name="realm" ref="myRealm"/>
> >         <property name="rememberMeManager" ref="myRememberMeManager"/>
> >     </bean>
> >     <bean name="myRememberMeManager"
> > class="com.project.security.MyRememberMeManager"/>
> >
> > On Tue, May 11, 2010 at 10:11 AM, Les Hazlewood <lh...@apache.org>
> > wrote:
> >>
> >> Hi Tauren,
> >>
> >> Yes, WebRememberMeManager has been deprecated in favor of the new
> >> CookieRememberMeManager which uses a new Cookie property and not the
> >> (now deprecated) CookieAttribute concept.  CookieAttribute was complex
> >> and confusing.  The new Cookie interface and implementation in
> >> comparison are much easier to understand and configure.  So, if you
> >> extend CookieRememberMeManager, you should be closely back to where
> >> you were when you extended WebRememberMeManager.
> >>
> >> As for the SubjectContext - it was added within the last two weeks to
> >> satisfy a technical requirement: the (now new) SubjectContext.resolve*
> >> method behavior was needed in multiple places across more than one OO
> >> hierarchy.  So, we either had to copy-n-paste logic (yuck) or
> >> consolidate it into a component.  The SubjectContext satisfies this
> >> need and will stay in place instead of the raw Map.
> >>
> >> Also note that for 1.0, we'll be removing all Deprecated classes and
> >> methods.  Since we're wrapping up coding issues today (and possibly
> >> tomorrow), we'll be deleting them any time now.
> >>
> >> I hope that helps!
> >>
> >> Les
> >>
> >> On Tue, May 11, 2010 at 9:22 AM, Tauren Mills <ta...@tauren.com>
> wrote:
> >> > I'm just getting back to this issue now, and have updated to the
> latest
> >> > shiro snapshot.
> >> > When I started working on this, I had extended WebRememberMeManager,
> but
> >> > it
> >> > looks like it is now depricated. What is the recommended approach at
> >> > this
> >> > time? Should I be directly extending AbstractRememberMeManager?
> >> > I also wanted to point out that your example in this thread shows
> >> > passing a
> >> > Map to getRememberedPrincipals, but in my experience I had to pass a
> >> > SubjectContext.  Before I proceed further, I just want to make sure
> that
> >> > I'm
> >> > heading down the proper path that will be supported in the future, and
> >> > not
> >> > implement something that I'll have to change later.
> >> > Thanks!
> >> > Tauren
> >> >
> >> >
> >> >
> >> >
> >> >
> >> >
> >> > On Mon, Apr 19, 2010 at 12:14 PM, Les Hazlewood <
> lhazlewood@apache.org>
> >> > wrote:
> >> >>
> >> >> I committed a change to how cryptography works on Friday - that might
> >> >> have done something with it (we encrypt principals by default).
> >> >> However, all the test cases still passed and I know that we do have
> >> >> some test cases around remember me cookies
> (WebRememberMeManagerTest).
> >> >>
> >> >> Please open a Jira issue in the mean time so we don't lose it.  I'll
> >> >> try to run the sample web app(s) to see if they exhibit the same
> >> >> behavior.
> >> >>
> >> >> Thanks!
> >> >>
> >> >> Les
> >> >>
> >> >> On Mon, Apr 19, 2010 at 10:57 AM, Tauren Mills <yo...@gmail.com>
> >> >> wrote:
> >> >> > It seems that my remember me function got broken at some point. All
> >> >> > of
> >> >> > my
> >> >> > requests do not have the cookie they used to. I've tried logging
> off
> >> >> > and
> >> >> > back in again, but still no cookie.  This is
> >> >> > causing getRememberedPrincipals
> >> >> > to run with every single request. Obviously not good.
> >> >> > Any suggestions on how to track down where the remember me problem
> is
> >> >> > coming
> >> >> > from - why I'm not getting cookies? I haven't done much of anything
> >> >> > with
> >> >> > Shiro for months now, and it used to work, so not sure what
> happened.
> >> >> > Was it
> >> >> > broken in some recent release that I may be using?
> >> >> > Thanks,
> >> >> > Tauren
> >> >> > On Mon, Apr 19, 2010 at 3:41 AM, Tauren Mills <yo...@gmail.com>
> >> >> > wrote:
> >> >> >>
> >> >> >> Les,
> >> >> >> Thanks, I'll look into doing this. Are there any examples of using
> >> >> >> an
> >> >> >> AuthenticationListener that I could reference?
> >> >> >>
> >> >> >> Tauren
> >> >> >>
> >> >> >> On Fri, Apr 16, 2010 at 9:10 AM, Les Hazlewood
> >> >> >> <lh...@apache.org>
> >> >> >> wrote:
> >> >> >>>
> >> >> >>> Hi Tauren,
> >> >> >>>
> >> >> >>> You could implement an AuthenticationListener - I typically like
> to
> >> >> >>> do
> >> >> >>> this for these kinds of operations.
> >> >> >>>
> >> >> >>> Since Shiro does not count remember me as a true authentication,
> >> >> >>> the
> >> >> >>> AuthenticationListener will not be triggered for remember me
> >> >> >>> events.
> >> >> >>> To do that you would also need to implement your own
> >> >> >>> RememberMeManager.  Typically subclassing the default one and
> >> >> >>> updating
> >> >> >>> the timestamp in the getRememberedPrincipals method would work:
> >> >> >>>
> >> >> >>> @Override
> >> >> >>> public PrincipalCollection getRememberedPrincipals(Map
> >> >> >>> subjectContext)
> >> >> >>> {
> >> >> >>>    PrincipalCollection principals =
> >> >> >>> super.getRememberedPrincipals(subjectContext);
> >> >> >>>    if ( principals != null ) {
> >> >> >>>        int userId = principals.getPrimaryPrincipal();
> >> >> >>>        //update the last login timestamp for user with this id
> here
> >> >> >>>    }
> >> >> >>> }
> >> >> >>>
> >> >> >>> The above method is called only if the current Subject/session
> does
> >> >> >>> not yet have an identity associated with it.
> >> >> >>>
> >> >> >>> The AuthenticationListener + the above overridden method should
> do
> >> >> >>> it!
> >> >> >>>
> >> >> >>> Cheers,
> >> >> >>>
> >> >> >>> Les
> >> >> >>>
> >> >> >>> On Thu, Apr 15, 2010 at 8:37 PM, Tauren Mills <
> tauren@groovee.com>
> >> >> >>> wrote:
> >> >> >>> > What would be the best way to update properties of a member on
> >> >> >>> > successful
> >> >> >>> > authentication? Basically, there is a Member.lastLogin property
> >> >> >>> > that
> >> >> >>> > I
> >> >> >>> > want
> >> >> >>> > updated with the current date every time a member comes back to
> a
> >> >> >>> > site
> >> >> >>> > and
> >> >> >>> > logs in.  However, this should also support rememberme
> >> >> >>> > authentications. I
> >> >> >>> > don't necessarily want to update the lastLogin property on
> every
> >> >> >>> > single
> >> >> >>> > interaction the user has on the site, just once for each
> session.
> >> >> >>> > Is there some technique in Shiro to do this, a callback of some
> >> >> >>> > sort,
> >> >> >>> > or
> >> >> >>> > some other method? Or should I be doing this in my application?
> >> >> >>> > Also, I can't seem to view much of the documentation. All the
> >> >> >>> > links
> >> >> >>> > on
> >> >> >>> > the
> >> >> >>> > following page require an Apache login. Is it supposed to be
> this
> >> >> >>> > way?
> >> >> >>> > http://incubator.apache.org/shiro/core.html
> >> >> >>> > Thanks!
> >> >> >>> > Tauren
> >> >> >>> >
> >> >> >>> >
> >> >> >>
> >> >> >
> >> >> >
> >> >
> >> >
> >
> >
>

Re: Keeping track of user's last login date

Posted by Les Hazlewood <lh...@apache.org>.
Sorry for the incoherent sentence resulting from poor proofreading:

"some requests attempt to be resolving the identity at the same time
and trying to update the session with the remembered identity"

I meant to say:

"some requests will attempt to resolve the identity at the same time
and try to update the session with the remembered identity"

:)

On Wed, May 12, 2010 at 12:03 PM, Les Hazlewood <lh...@apache.org> wrote:
> Hi Tauren,
>
> You discovered an interesting scenario.  Yes, it makes sense that the
> RememberMeManager would be consulted frequently if there are many
> different anonymous requests to the application, such as when a user
> with new session visits a home page which happens to have many
> resources (images, css, etc).
>
> But, the SecurityManager implementation should not continually
> reference the RememberMeManager once the identity is discovered - they
> are already 'remembered' at that point and there is no point in
> continuing to discover the identity.
>
> I've created a Jira issue to represent this:
>
> https://issues.apache.org/jira/browse/SHIRO-157
>
> And I'll work on it right away - it is definitely important enough to
> make it into 1.0.
>
> But realize that if a user with a new session visits a web page that
> requires many requests and those requests are filtered by the
> ShiroFilter (such as images, CSS, etc) you will have a race condition
> - some requests attempt to be resolving the identity at the same time
> and trying to update the session with the remembered identity.  Once
> any one of them updates the session, all other subsequent requests
> won't go through the rememberMe process.
>
> This is not critical really - you just might have one or two requests
> do unnecessary work.  Just be aware that your
> memberService.updateAccess could get called a small number of times
> before stopping for that user.
>
> So, there are two ways that I can think of off the top of my head to
> reduce or eliminate this problem:
>
> 1.  Don't have the ShiroFilter filter URLs that you don't think need
> security access/user association.  I typically do not have static
> assets (images, CSS, JavaScript, etc) filtered by Shiro since I
> usually don't find it necessary to secure these.  But, everyone has
> different requirements, so I'll leave that up to you.
>
> 2.  Honestly the best way I can think do this is via a SessionListener
> (this requires using 'native' sessions).  When the session stops or
> expires, the SessionListener can pull the user identity from the
> session and then update the member access time based on that identity.
>  Most people use the session's lastAccessTime property for this.  It
> is also cleaner in that you can implement a Listener intended for this
> type of behavior rather than having to subclass a Shiro implementation
> class.  But the one caveat here is that you can't update that
> timestamp at the moment their identity is discovered.  But in
> practice, most people don't care about that usually, but again,
> requirements differ.
>
> Does that help?
>
> Les
>
> On Wed, May 12, 2010 at 9:49 AM, Tauren Mills <ta...@tauren.com> wrote:
>> Les,
>> Thanks for the help.  However, now I'm having a problem
>> with getRememberedPrincipals() being called dozens of times per page
>> view, causing my "accessed" property to be updated many times, which is
>> obviously not ideal.
>> I believe this is because my application is running in Jetty, so every
>> image, JS, CSS, and other resource is causing a request to be created. My
>> cookie is set to / since I need it to work for many different paths.
>> Any suggestions on how to only update my "accessed" property a single time
>> per session?  I don't need the property updated with every request, just
>> when they first access the site for a session is fine.  Basically, the
>> property I currently called "accessed" would actually be more accurately
>> called "lastLogin".
>> Below is code if it helps.
>> Thanks,
>> Tauren
>> ---
>> public class MyRememberMeManager extends CookieRememberMeManager {
>> private MemberService memberService;
>>     @Autowired
>> public void setMemberService(MemberService memberService) {
>> this.memberService = memberService;
>> }
>> @Override
>> public PrincipalCollection getRememberedPrincipals(SubjectContext
>> subjectContext) {
>> PrincipalCollection principals =
>> super.getRememberedPrincipals(subjectContext);
>> if ( principals != null ) {
>> Long id = (Long) principals.getPrimaryPrincipal();
>> memberService.updateAccessed(id);
>> }
>> return principals;
>> }
>> }
>> // MemberServiceImpl.java
>> public void updateAccessed(Long id) {
>> updateAccessed(findById(id));
>> }
>> public void updateAccessed(Member member) {
>> member.setAccessed(new Date());
>> memberDao.save(member);
>> }
>>
>> // Spring config
>>     <bean id="securityManager"
>> class="org.apache.shiro.web.DefaultWebSecurityManager">
>>       property instead. -->
>>         <property name="realm" ref="myRealm"/>
>>         <property name="rememberMeManager" ref="myRememberMeManager"/>
>>     </bean>
>>     <bean name="myRememberMeManager"
>> class="com.project.security.MyRememberMeManager"/>
>>
>> On Tue, May 11, 2010 at 10:11 AM, Les Hazlewood <lh...@apache.org>
>> wrote:
>>>
>>> Hi Tauren,
>>>
>>> Yes, WebRememberMeManager has been deprecated in favor of the new
>>> CookieRememberMeManager which uses a new Cookie property and not the
>>> (now deprecated) CookieAttribute concept.  CookieAttribute was complex
>>> and confusing.  The new Cookie interface and implementation in
>>> comparison are much easier to understand and configure.  So, if you
>>> extend CookieRememberMeManager, you should be closely back to where
>>> you were when you extended WebRememberMeManager.
>>>
>>> As for the SubjectContext - it was added within the last two weeks to
>>> satisfy a technical requirement: the (now new) SubjectContext.resolve*
>>> method behavior was needed in multiple places across more than one OO
>>> hierarchy.  So, we either had to copy-n-paste logic (yuck) or
>>> consolidate it into a component.  The SubjectContext satisfies this
>>> need and will stay in place instead of the raw Map.
>>>
>>> Also note that for 1.0, we'll be removing all Deprecated classes and
>>> methods.  Since we're wrapping up coding issues today (and possibly
>>> tomorrow), we'll be deleting them any time now.
>>>
>>> I hope that helps!
>>>
>>> Les
>>>
>>> On Tue, May 11, 2010 at 9:22 AM, Tauren Mills <ta...@tauren.com> wrote:
>>> > I'm just getting back to this issue now, and have updated to the latest
>>> > shiro snapshot.
>>> > When I started working on this, I had extended WebRememberMeManager, but
>>> > it
>>> > looks like it is now depricated. What is the recommended approach at
>>> > this
>>> > time? Should I be directly extending AbstractRememberMeManager?
>>> > I also wanted to point out that your example in this thread shows
>>> > passing a
>>> > Map to getRememberedPrincipals, but in my experience I had to pass a
>>> > SubjectContext.  Before I proceed further, I just want to make sure that
>>> > I'm
>>> > heading down the proper path that will be supported in the future, and
>>> > not
>>> > implement something that I'll have to change later.
>>> > Thanks!
>>> > Tauren
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> > On Mon, Apr 19, 2010 at 12:14 PM, Les Hazlewood <lh...@apache.org>
>>> > wrote:
>>> >>
>>> >> I committed a change to how cryptography works on Friday - that might
>>> >> have done something with it (we encrypt principals by default).
>>> >> However, all the test cases still passed and I know that we do have
>>> >> some test cases around remember me cookies (WebRememberMeManagerTest).
>>> >>
>>> >> Please open a Jira issue in the mean time so we don't lose it.  I'll
>>> >> try to run the sample web app(s) to see if they exhibit the same
>>> >> behavior.
>>> >>
>>> >> Thanks!
>>> >>
>>> >> Les
>>> >>
>>> >> On Mon, Apr 19, 2010 at 10:57 AM, Tauren Mills <yo...@gmail.com>
>>> >> wrote:
>>> >> > It seems that my remember me function got broken at some point. All
>>> >> > of
>>> >> > my
>>> >> > requests do not have the cookie they used to. I've tried logging off
>>> >> > and
>>> >> > back in again, but still no cookie.  This is
>>> >> > causing getRememberedPrincipals
>>> >> > to run with every single request. Obviously not good.
>>> >> > Any suggestions on how to track down where the remember me problem is
>>> >> > coming
>>> >> > from - why I'm not getting cookies? I haven't done much of anything
>>> >> > with
>>> >> > Shiro for months now, and it used to work, so not sure what happened.
>>> >> > Was it
>>> >> > broken in some recent release that I may be using?
>>> >> > Thanks,
>>> >> > Tauren
>>> >> > On Mon, Apr 19, 2010 at 3:41 AM, Tauren Mills <yo...@gmail.com>
>>> >> > wrote:
>>> >> >>
>>> >> >> Les,
>>> >> >> Thanks, I'll look into doing this. Are there any examples of using
>>> >> >> an
>>> >> >> AuthenticationListener that I could reference?
>>> >> >>
>>> >> >> Tauren
>>> >> >>
>>> >> >> On Fri, Apr 16, 2010 at 9:10 AM, Les Hazlewood
>>> >> >> <lh...@apache.org>
>>> >> >> wrote:
>>> >> >>>
>>> >> >>> Hi Tauren,
>>> >> >>>
>>> >> >>> You could implement an AuthenticationListener - I typically like to
>>> >> >>> do
>>> >> >>> this for these kinds of operations.
>>> >> >>>
>>> >> >>> Since Shiro does not count remember me as a true authentication,
>>> >> >>> the
>>> >> >>> AuthenticationListener will not be triggered for remember me
>>> >> >>> events.
>>> >> >>> To do that you would also need to implement your own
>>> >> >>> RememberMeManager.  Typically subclassing the default one and
>>> >> >>> updating
>>> >> >>> the timestamp in the getRememberedPrincipals method would work:
>>> >> >>>
>>> >> >>> @Override
>>> >> >>> public PrincipalCollection getRememberedPrincipals(Map
>>> >> >>> subjectContext)
>>> >> >>> {
>>> >> >>>    PrincipalCollection principals =
>>> >> >>> super.getRememberedPrincipals(subjectContext);
>>> >> >>>    if ( principals != null ) {
>>> >> >>>        int userId = principals.getPrimaryPrincipal();
>>> >> >>>        //update the last login timestamp for user with this id here
>>> >> >>>    }
>>> >> >>> }
>>> >> >>>
>>> >> >>> The above method is called only if the current Subject/session does
>>> >> >>> not yet have an identity associated with it.
>>> >> >>>
>>> >> >>> The AuthenticationListener + the above overridden method should do
>>> >> >>> it!
>>> >> >>>
>>> >> >>> Cheers,
>>> >> >>>
>>> >> >>> Les
>>> >> >>>
>>> >> >>> On Thu, Apr 15, 2010 at 8:37 PM, Tauren Mills <ta...@groovee.com>
>>> >> >>> wrote:
>>> >> >>> > What would be the best way to update properties of a member on
>>> >> >>> > successful
>>> >> >>> > authentication? Basically, there is a Member.lastLogin property
>>> >> >>> > that
>>> >> >>> > I
>>> >> >>> > want
>>> >> >>> > updated with the current date every time a member comes back to a
>>> >> >>> > site
>>> >> >>> > and
>>> >> >>> > logs in.  However, this should also support rememberme
>>> >> >>> > authentications. I
>>> >> >>> > don't necessarily want to update the lastLogin property on every
>>> >> >>> > single
>>> >> >>> > interaction the user has on the site, just once for each session.
>>> >> >>> > Is there some technique in Shiro to do this, a callback of some
>>> >> >>> > sort,
>>> >> >>> > or
>>> >> >>> > some other method? Or should I be doing this in my application?
>>> >> >>> > Also, I can't seem to view much of the documentation. All the
>>> >> >>> > links
>>> >> >>> > on
>>> >> >>> > the
>>> >> >>> > following page require an Apache login. Is it supposed to be this
>>> >> >>> > way?
>>> >> >>> > http://incubator.apache.org/shiro/core.html
>>> >> >>> > Thanks!
>>> >> >>> > Tauren
>>> >> >>> >
>>> >> >>> >
>>> >> >>
>>> >> >
>>> >> >
>>> >
>>> >
>>
>>
>

Re: Keeping track of user's last login date

Posted by Les Hazlewood <lh...@apache.org>.
Hi Tauren,

You discovered an interesting scenario.  Yes, it makes sense that the
RememberMeManager would be consulted frequently if there are many
different anonymous requests to the application, such as when a user
with new session visits a home page which happens to have many
resources (images, css, etc).

But, the SecurityManager implementation should not continually
reference the RememberMeManager once the identity is discovered - they
are already 'remembered' at that point and there is no point in
continuing to discover the identity.

I've created a Jira issue to represent this:

https://issues.apache.org/jira/browse/SHIRO-157

And I'll work on it right away - it is definitely important enough to
make it into 1.0.

But realize that if a user with a new session visits a web page that
requires many requests and those requests are filtered by the
ShiroFilter (such as images, CSS, etc) you will have a race condition
- some requests attempt to be resolving the identity at the same time
and trying to update the session with the remembered identity.  Once
any one of them updates the session, all other subsequent requests
won't go through the rememberMe process.

This is not critical really - you just might have one or two requests
do unnecessary work.  Just be aware that your
memberService.updateAccess could get called a small number of times
before stopping for that user.

So, there are two ways that I can think of off the top of my head to
reduce or eliminate this problem:

1.  Don't have the ShiroFilter filter URLs that you don't think need
security access/user association.  I typically do not have static
assets (images, CSS, JavaScript, etc) filtered by Shiro since I
usually don't find it necessary to secure these.  But, everyone has
different requirements, so I'll leave that up to you.

2.  Honestly the best way I can think do this is via a SessionListener
(this requires using 'native' sessions).  When the session stops or
expires, the SessionListener can pull the user identity from the
session and then update the member access time based on that identity.
 Most people use the session's lastAccessTime property for this.  It
is also cleaner in that you can implement a Listener intended for this
type of behavior rather than having to subclass a Shiro implementation
class.  But the one caveat here is that you can't update that
timestamp at the moment their identity is discovered.  But in
practice, most people don't care about that usually, but again,
requirements differ.

Does that help?

Les

On Wed, May 12, 2010 at 9:49 AM, Tauren Mills <ta...@tauren.com> wrote:
> Les,
> Thanks for the help.  However, now I'm having a problem
> with getRememberedPrincipals() being called dozens of times per page
> view, causing my "accessed" property to be updated many times, which is
> obviously not ideal.
> I believe this is because my application is running in Jetty, so every
> image, JS, CSS, and other resource is causing a request to be created. My
> cookie is set to / since I need it to work for many different paths.
> Any suggestions on how to only update my "accessed" property a single time
> per session?  I don't need the property updated with every request, just
> when they first access the site for a session is fine.  Basically, the
> property I currently called "accessed" would actually be more accurately
> called "lastLogin".
> Below is code if it helps.
> Thanks,
> Tauren
> ---
> public class MyRememberMeManager extends CookieRememberMeManager {
> private MemberService memberService;
>     @Autowired
> public void setMemberService(MemberService memberService) {
> this.memberService = memberService;
> }
> @Override
> public PrincipalCollection getRememberedPrincipals(SubjectContext
> subjectContext) {
> PrincipalCollection principals =
> super.getRememberedPrincipals(subjectContext);
> if ( principals != null ) {
> Long id = (Long) principals.getPrimaryPrincipal();
> memberService.updateAccessed(id);
> }
> return principals;
> }
> }
> // MemberServiceImpl.java
> public void updateAccessed(Long id) {
> updateAccessed(findById(id));
> }
> public void updateAccessed(Member member) {
> member.setAccessed(new Date());
> memberDao.save(member);
> }
>
> // Spring config
>     <bean id="securityManager"
> class="org.apache.shiro.web.DefaultWebSecurityManager">
>       property instead. -->
>         <property name="realm" ref="myRealm"/>
>         <property name="rememberMeManager" ref="myRememberMeManager"/>
>     </bean>
>     <bean name="myRememberMeManager"
> class="com.project.security.MyRememberMeManager"/>
>
> On Tue, May 11, 2010 at 10:11 AM, Les Hazlewood <lh...@apache.org>
> wrote:
>>
>> Hi Tauren,
>>
>> Yes, WebRememberMeManager has been deprecated in favor of the new
>> CookieRememberMeManager which uses a new Cookie property and not the
>> (now deprecated) CookieAttribute concept.  CookieAttribute was complex
>> and confusing.  The new Cookie interface and implementation in
>> comparison are much easier to understand and configure.  So, if you
>> extend CookieRememberMeManager, you should be closely back to where
>> you were when you extended WebRememberMeManager.
>>
>> As for the SubjectContext - it was added within the last two weeks to
>> satisfy a technical requirement: the (now new) SubjectContext.resolve*
>> method behavior was needed in multiple places across more than one OO
>> hierarchy.  So, we either had to copy-n-paste logic (yuck) or
>> consolidate it into a component.  The SubjectContext satisfies this
>> need and will stay in place instead of the raw Map.
>>
>> Also note that for 1.0, we'll be removing all Deprecated classes and
>> methods.  Since we're wrapping up coding issues today (and possibly
>> tomorrow), we'll be deleting them any time now.
>>
>> I hope that helps!
>>
>> Les
>>
>> On Tue, May 11, 2010 at 9:22 AM, Tauren Mills <ta...@tauren.com> wrote:
>> > I'm just getting back to this issue now, and have updated to the latest
>> > shiro snapshot.
>> > When I started working on this, I had extended WebRememberMeManager, but
>> > it
>> > looks like it is now depricated. What is the recommended approach at
>> > this
>> > time? Should I be directly extending AbstractRememberMeManager?
>> > I also wanted to point out that your example in this thread shows
>> > passing a
>> > Map to getRememberedPrincipals, but in my experience I had to pass a
>> > SubjectContext.  Before I proceed further, I just want to make sure that
>> > I'm
>> > heading down the proper path that will be supported in the future, and
>> > not
>> > implement something that I'll have to change later.
>> > Thanks!
>> > Tauren
>> >
>> >
>> >
>> >
>> >
>> >
>> > On Mon, Apr 19, 2010 at 12:14 PM, Les Hazlewood <lh...@apache.org>
>> > wrote:
>> >>
>> >> I committed a change to how cryptography works on Friday - that might
>> >> have done something with it (we encrypt principals by default).
>> >> However, all the test cases still passed and I know that we do have
>> >> some test cases around remember me cookies (WebRememberMeManagerTest).
>> >>
>> >> Please open a Jira issue in the mean time so we don't lose it.  I'll
>> >> try to run the sample web app(s) to see if they exhibit the same
>> >> behavior.
>> >>
>> >> Thanks!
>> >>
>> >> Les
>> >>
>> >> On Mon, Apr 19, 2010 at 10:57 AM, Tauren Mills <yo...@gmail.com>
>> >> wrote:
>> >> > It seems that my remember me function got broken at some point. All
>> >> > of
>> >> > my
>> >> > requests do not have the cookie they used to. I've tried logging off
>> >> > and
>> >> > back in again, but still no cookie.  This is
>> >> > causing getRememberedPrincipals
>> >> > to run with every single request. Obviously not good.
>> >> > Any suggestions on how to track down where the remember me problem is
>> >> > coming
>> >> > from - why I'm not getting cookies? I haven't done much of anything
>> >> > with
>> >> > Shiro for months now, and it used to work, so not sure what happened.
>> >> > Was it
>> >> > broken in some recent release that I may be using?
>> >> > Thanks,
>> >> > Tauren
>> >> > On Mon, Apr 19, 2010 at 3:41 AM, Tauren Mills <yo...@gmail.com>
>> >> > wrote:
>> >> >>
>> >> >> Les,
>> >> >> Thanks, I'll look into doing this. Are there any examples of using
>> >> >> an
>> >> >> AuthenticationListener that I could reference?
>> >> >>
>> >> >> Tauren
>> >> >>
>> >> >> On Fri, Apr 16, 2010 at 9:10 AM, Les Hazlewood
>> >> >> <lh...@apache.org>
>> >> >> wrote:
>> >> >>>
>> >> >>> Hi Tauren,
>> >> >>>
>> >> >>> You could implement an AuthenticationListener - I typically like to
>> >> >>> do
>> >> >>> this for these kinds of operations.
>> >> >>>
>> >> >>> Since Shiro does not count remember me as a true authentication,
>> >> >>> the
>> >> >>> AuthenticationListener will not be triggered for remember me
>> >> >>> events.
>> >> >>> To do that you would also need to implement your own
>> >> >>> RememberMeManager.  Typically subclassing the default one and
>> >> >>> updating
>> >> >>> the timestamp in the getRememberedPrincipals method would work:
>> >> >>>
>> >> >>> @Override
>> >> >>> public PrincipalCollection getRememberedPrincipals(Map
>> >> >>> subjectContext)
>> >> >>> {
>> >> >>>    PrincipalCollection principals =
>> >> >>> super.getRememberedPrincipals(subjectContext);
>> >> >>>    if ( principals != null ) {
>> >> >>>        int userId = principals.getPrimaryPrincipal();
>> >> >>>        //update the last login timestamp for user with this id here
>> >> >>>    }
>> >> >>> }
>> >> >>>
>> >> >>> The above method is called only if the current Subject/session does
>> >> >>> not yet have an identity associated with it.
>> >> >>>
>> >> >>> The AuthenticationListener + the above overridden method should do
>> >> >>> it!
>> >> >>>
>> >> >>> Cheers,
>> >> >>>
>> >> >>> Les
>> >> >>>
>> >> >>> On Thu, Apr 15, 2010 at 8:37 PM, Tauren Mills <ta...@groovee.com>
>> >> >>> wrote:
>> >> >>> > What would be the best way to update properties of a member on
>> >> >>> > successful
>> >> >>> > authentication? Basically, there is a Member.lastLogin property
>> >> >>> > that
>> >> >>> > I
>> >> >>> > want
>> >> >>> > updated with the current date every time a member comes back to a
>> >> >>> > site
>> >> >>> > and
>> >> >>> > logs in.  However, this should also support rememberme
>> >> >>> > authentications. I
>> >> >>> > don't necessarily want to update the lastLogin property on every
>> >> >>> > single
>> >> >>> > interaction the user has on the site, just once for each session.
>> >> >>> > Is there some technique in Shiro to do this, a callback of some
>> >> >>> > sort,
>> >> >>> > or
>> >> >>> > some other method? Or should I be doing this in my application?
>> >> >>> > Also, I can't seem to view much of the documentation. All the
>> >> >>> > links
>> >> >>> > on
>> >> >>> > the
>> >> >>> > following page require an Apache login. Is it supposed to be this
>> >> >>> > way?
>> >> >>> > http://incubator.apache.org/shiro/core.html
>> >> >>> > Thanks!
>> >> >>> > Tauren
>> >> >>> >
>> >> >>> >
>> >> >>
>> >> >
>> >> >
>> >
>> >
>
>

Re: Keeping track of user's last login date

Posted by Tauren Mills <ta...@tauren.com>.
Les,

Thanks, this works perfectly. Note that I had to use encodeToString()
instead of encode():

int keySize = 128;
String key = Base64.encodeToString(new
AesCipherService().generateNewKey(keySize).getEncoded());

I'll just ignore the exceptions in the logs, as they will eventually go away
when everyone has a new cookie.

Tauren



On Wed, May 12, 2010 at 1:51 PM, Les Hazlewood <lh...@apache.org>wrote:

> Hi Tauren,
>
> The easiest way is to probably use the MethodInvokingFactoryBean for this:
>
> <bean id="myRememberMeManager" class="...">
>    <property name="cipherKey" ref="cipherKeyBytes"/>
> </bean>
>
> <bean id="cipherKeyBytes"
> class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
>   <property name="targetClass" value="org.apache.shiro.codec.Base64"/>
>   <property name="targetMethod" value="decode"/>
>   <property name="arguments">
>     <list>
>       <value>your_base64_encoded_string</value>
>     </list>
>   </property>
> </bean>
>
> Cheers,
>
> Les
>
> On Wed, May 12, 2010 at 12:58 PM, Tauren Mills <ta...@tauren.com> wrote:
> > Les,
> > Thanks, this is helpful. I'd like to use my own custom cipherKey, but I'm
> > not using INI configuration. Could you perhaps explain how to configure
> this
> > using Spring instead of INI? I think this too would be useful information
> to
> > go into the wiki.  Here's my current spring config:
> >   <bean id="securityManager"
> > class="org.apache.shiro.web.DefaultWebSecurityManager">
> >     <property name="realm" ref="myRealm"/>
> >     <property name="rememberMeManager" ref="myRememberMeManager"/>
> >   </bean>
> >   <bean name="myRememberMeManager"
> > class="com.project.security.MyRememberMeManager"/>
> > Thanks!
> > Tauren
> >
> > On Wed, May 12, 2010 at 12:24 PM, Les Hazlewood <lh...@apache.org>
> > wrote:
> >>
> >> Yep, you're exactly right - it is because of the new (more secure)
> >> CipherService instances.  I would ignore these warnings - the
> >> rememberMe cookie will be deleted and a new correct one will be
> >> auto-created the next time they log in (and they click 'remember me'
> >> of course).
> >>
> >> If you didn't want to ignore them and have them just work, you can do 3
> >> things:
> >>
> >> 1.  Configure the RememberMeManager to use the BlowfishCipherService.
> >> Prior to the 1.0 release, we defaulted to using the Blowfish
> >> algorithm, but most people prefer AES, so now we default to the
> >> AesCipherService.
> >> 2.  Ensure that the new BlowfishCipherService is using the _exact_
> >> same key that was used before.  This is simple if you're using your
> >> own cipher key.  It is harder if you were using Shiro's default
> >> blowfish key, at which point you would need to look at the old source
> >> code to find it.
> >> 3.  Ensure that your BlowfishCipherService instance's
> >> 'generateInitializationVectors' attribute is set to false.
> >>
> >> Step 3 makes the encryption less secure and overall 1-3 can be a pain.
> >>  I'd recommend just ignoring the warnings for now and let the new
> >> cookies replace the old ones if you are ok with that.
> >>
> >> One thing you might want to try is using your own cipher key with the
> >> CipherService instance - it makes it more secure instead of using
> >> Shiro's default (which could be discovered by a 3rd party).  To be
> >> fair, the encrypted data is just a serialized PrincipalCollection, so
> >> if you're not storing sensitive data in the PC, you don't really need
> >> to do this.  I still like to do it though in case I ever do need to
> >> use an AES Cipher to encrypt something sensitive - then my key is all
> >> ready to go.
> >>
> >> You can do this by doing the following:
> >>
> >> //AES algorithm only supports key sizes of 128, 192, and 256 bits.
> >> //192 and 256 require that the JCE Unlimited Strength
> >> //Jurisdiction Policy files to be installed.
> >> int keySize = 128;
> >> String key = Base64.encode(new
> >> AesCipherService().generateNewKey(keySize).getEncoded());
> >>
> >> //then you can use this key in your shiro config:
> >>
> >> [main]
> >> securityManager.rememberMeManager.cipherKey =
> >> your_base64_encoded_string_from_above
> >>
> >> The configurator will automatically recognize that is a byte array
> >> property and Base64 decode the string value into the correct bytes.
> >> If you wanted to use Hex encoding instead, make sure you prefix your
> >> encoded string with 0x ('zero' 'x'):
> >>
> >> securityManager.rememberMeManager.cipherKey = 0x123456789ABCDEF
> >>
> >> which will trigger Hex decoding instead.
> >>
> >> I know I've rambled on about this, but hopefully this will be indexed
> >> by Google and help someone else in the future.  It also gives me a
> >> base to use to update the wiki documentation :)
> >>
> >> Cheers,
> >>
> >> Les
> >>
> >> 1.  Ensure that the cipher service is using the same cipher key
> >> you could configure your CipherService to set
> >> 'generateInitializationVectors' to false, in which case the previou
> >>
> >> On Wed, May 12, 2010 at 11:08 AM, Tauren Mills <ta...@tauren.com>
> wrote:
> >> > Also, I'm getting the following exception in my logs. I'm assuming
> that
> >> > is
> >> > just because people have old cookies with old cyphers, and that once
> >> > their
> >> > cookies are replaced, I won't see these exceptions anymore. I also
> >> > assume
> >> > this means that everyone is being forced to log in again since my app
> >> > has
> >> > been updated with the latest shiro and that no existing rememberme
> >> > cookies
> >> > will work.  Is this correct?
> >> > Thanks,
> >> > Tauren
> >> > ---
> >> >
> >> > WARN  - DefaultSecurityManager     - Delegate RememberMeManager
> instance
> >> > of
> >> > type [com.project.security.MyRememberMeManager] threw an exception
> >> > during
> >> > getRememberedPrincipals().
> >> > org.apache.shiro.crypto.CryptoException: Unable to execute 'doFinal'
> >> > with
> >> > cipher instance [javax.crypto.Cipher@5b3bd1c0].
> >> > at
> >> >
> org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:465)
> >> > at
> >> >
> org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:448)
> >> > at
> >> >
> >> >
> org.apache.shiro.crypto.JcaCipherService.decrypt(JcaCipherService.java:393)
> >> > at
> >> >
> >> >
> org.apache.shiro.crypto.JcaCipherService.decrypt(JcaCipherService.java:385)
> >> > at
> >> >
> >> >
> org.apache.shiro.mgt.AbstractRememberMeManager.decrypt(AbstractRememberMeManager.java:491)
> >> > at
> >> >
> >> >
> org.apache.shiro.mgt.AbstractRememberMeManager.convertBytesToPrincipals(AbstractRememberMeManager.java:431)
> >> > at
> >> >
> >> >
> org.apache.shiro.mgt.AbstractRememberMeManager.getRememberedPrincipals(AbstractRememberMeManager.java:398)
> >> > at
> >> >
> >> >
> com.project.security.MyRememberMeManager.getRememberedPrincipals(MyRememberMeManager.java:21)
> >> > at
> >> >
> >> >
> org.apache.shiro.mgt.DefaultSecurityManager.getRememberedIdentity(DefaultSecurityManager.java:526)
> >> > at
> >> >
> >> >
> org.apache.shiro.mgt.DefaultSecurityManager.resolvePrincipals(DefaultSecurityManager.java:403)
> >> > at
> >> >
> >> >
> org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:320)
> >> > at
> >> >
> org.apache.shiro.subject.Subject$Builder.buildSubject(Subject.java:767)
> >> > at
> >> >
> >> >
> org.apache.shiro.web.subject.WebSubject$Builder.buildWebSubject(WebSubject.java:101)
> >> > at org.apache.shiro.web.servlet.ShiroFilter.bind(ShiroFilter.java:540)
> >> > at
> >> >
> >> >
> org.apache.shiro.web.servlet.ShiroFilter.doFilterInternal(ShiroFilter.java:627)
> >> > at
> >> >
> >> >
> org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:83)
> >> > at
> >> >
> >> >
> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088)
> >> > at
> >> >
> >> >
> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
> >> > at
> >> >
> >> >
> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
> >> > at
> >> >
> >> >
> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088)
> >> > at
> >> >
> org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
> >> > at
> >> >
> >> >
> org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
> >> > at
> >> >
> org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
> >> > at
> >> >
> org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
> >> > at
> org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
> >> > at
> >> >
> org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
> >> > at org.mortbay.jetty.Server.handle(Server.java:324)
> >> > at
> >> >
> org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
> >> > at
> >> >
> >> >
> org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:829)
> >> > at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:513)
> >> > at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
> >> > at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
> >> > at
> >> >
> >> >
> org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)
> >> > at
> >> >
> >> >
> org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
> >> > Caused by: javax.crypto.BadPaddingException: Given final block not
> >> > properly
> >> > padded
> >> > at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
> >> > at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
> >> > at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
> >> > at javax.crypto.Cipher.doFinal(DashoA13*..)
> >> > at
> >> >
> org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:462)
> >> > ... 33 more
> >> >
> >> > On Wed, May 12, 2010 at 9:49 AM, Tauren Mills <ta...@tauren.com>
> wrote:
> >> >>
> >> >> Les,
> >> >> Thanks for the help.  However, now I'm having a problem
> >> >> with getRememberedPrincipals() being called dozens of times per page
> >> >> view, causing my "accessed" property to be updated many times, which
> is
> >> >> obviously not ideal.
> >> >> I believe this is because my application is running in Jetty, so
> every
> >> >> image, JS, CSS, and other resource is causing a request to be
> created.
> >> >> My
> >> >> cookie is set to / since I need it to work for many different paths.
> >> >> Any suggestions on how to only update my "accessed" property a single
> >> >> time
> >> >> per session?  I don't need the property updated with every request,
> >> >> just
> >> >> when they first access the site for a session is fine.  Basically,
> the
> >> >> property I currently called "accessed" would actually be more
> >> >> accurately
> >> >> called "lastLogin".
> >> >> Below is code if it helps.
> >> >> Thanks,
> >> >> Tauren
> >> >> ---
> >> >> public class MyRememberMeManager extends CookieRememberMeManager {
> >> >> private MemberService memberService;
> >> >>     @Autowired
> >> >> public void setMemberService(MemberService memberService) {
> >> >> this.memberService = memberService;
> >> >> }
> >> >> @Override
> >> >> public PrincipalCollection getRememberedPrincipals(SubjectContext
> >> >> subjectContext) {
> >> >> PrincipalCollection principals =
> >> >> super.getRememberedPrincipals(subjectContext);
> >> >> if ( principals != null ) {
> >> >> Long id = (Long) principals.getPrimaryPrincipal();
> >> >> memberService.updateAccessed(id);
> >> >> }
> >> >> return principals;
> >> >> }
> >> >> }
> >> >> // MemberServiceImpl.java
> >> >> public void updateAccessed(Long id) {
> >> >> updateAccessed(findById(id));
> >> >> }
> >> >> public void updateAccessed(Member member) {
> >> >> member.setAccessed(new Date());
> >> >> memberDao.save(member);
> >> >> }
> >> >>
> >> >> // Spring config
> >> >>     <bean id="securityManager"
> >> >> class="org.apache.shiro.web.DefaultWebSecurityManager">
> >> >>       property instead. -->
> >> >>         <property name="realm" ref="myRealm"/>
> >> >>         <property name="rememberMeManager"
> ref="myRememberMeManager"/>
> >> >>     </bean>
> >> >>     <bean name="myRememberMeManager"
> >> >> class="com.project.security.MyRememberMeManager"/>
> >> >>
> >> >> On Tue, May 11, 2010 at 10:11 AM, Les Hazlewood <
> lhazlewood@apache.org>
> >> >> wrote:
> >> >>>
> >> >>> Hi Tauren,
> >> >>>
> >> >>> Yes, WebRememberMeManager has been deprecated in favor of the new
> >> >>> CookieRememberMeManager which uses a new Cookie property and not the
> >> >>> (now deprecated) CookieAttribute concept.  CookieAttribute was
> complex
> >> >>> and confusing.  The new Cookie interface and implementation in
> >> >>> comparison are much easier to understand and configure.  So, if you
> >> >>> extend CookieRememberMeManager, you should be closely back to where
> >> >>> you were when you extended WebRememberMeManager.
> >> >>>
> >> >>> As for the SubjectContext - it was added within the last two weeks
> to
> >> >>> satisfy a technical requirement: the (now new)
> SubjectContext.resolve*
> >> >>> method behavior was needed in multiple places across more than one
> OO
> >> >>> hierarchy.  So, we either had to copy-n-paste logic (yuck) or
> >> >>> consolidate it into a component.  The SubjectContext satisfies this
> >> >>> need and will stay in place instead of the raw Map.
> >> >>>
> >> >>> Also note that for 1.0, we'll be removing all Deprecated classes and
> >> >>> methods.  Since we're wrapping up coding issues today (and possibly
> >> >>> tomorrow), we'll be deleting them any time now.
> >> >>>
> >> >>> I hope that helps!
> >> >>>
> >> >>> Les
> >> >>>
> >> >>> On Tue, May 11, 2010 at 9:22 AM, Tauren Mills <ta...@tauren.com>
> >> >>> wrote:
> >> >>> > I'm just getting back to this issue now, and have updated to the
> >> >>> > latest
> >> >>> > shiro snapshot.
> >> >>> > When I started working on this, I had extended
> WebRememberMeManager,
> >> >>> > but it
> >> >>> > looks like it is now depricated. What is the recommended approach
> at
> >> >>> > this
> >> >>> > time? Should I be directly extending AbstractRememberMeManager?
> >> >>> > I also wanted to point out that your example in this thread shows
> >> >>> > passing a
> >> >>> > Map to getRememberedPrincipals, but in my experience I had to pass
> a
> >> >>> > SubjectContext.  Before I proceed further, I just want to make
> sure
> >> >>> > that I'm
> >> >>> > heading down the proper path that will be supported in the future,
> >> >>> > and
> >> >>> > not
> >> >>> > implement something that I'll have to change later.
> >> >>> > Thanks!
> >> >>> > Tauren
> >> >>> >
> >> >>> >
> >> >>> >
> >> >>> >
> >> >>> >
> >> >>> >
> >> >>> > On Mon, Apr 19, 2010 at 12:14 PM, Les Hazlewood
> >> >>> > <lh...@apache.org>
> >> >>> > wrote:
> >> >>> >>
> >> >>> >> I committed a change to how cryptography works on Friday - that
> >> >>> >> might
> >> >>> >> have done something with it (we encrypt principals by default).
> >> >>> >> However, all the test cases still passed and I know that we do
> have
> >> >>> >> some test cases around remember me cookies
> >> >>> >> (WebRememberMeManagerTest).
> >> >>> >>
> >> >>> >> Please open a Jira issue in the mean time so we don't lose it.
> >> >>> >>  I'll
> >> >>> >> try to run the sample web app(s) to see if they exhibit the same
> >> >>> >> behavior.
> >> >>> >>
> >> >>> >> Thanks!
> >> >>> >>
> >> >>> >> Les
> >> >>> >>
> >> >>> >> On Mon, Apr 19, 2010 at 10:57 AM, Tauren Mills <
> yowzator@gmail.com>
> >> >>> >> wrote:
> >> >>> >> > It seems that my remember me function got broken at some point.
> >> >>> >> > All
> >> >>> >> > of
> >> >>> >> > my
> >> >>> >> > requests do not have the cookie they used to. I've tried
> logging
> >> >>> >> > off
> >> >>> >> > and
> >> >>> >> > back in again, but still no cookie.  This is
> >> >>> >> > causing getRememberedPrincipals
> >> >>> >> > to run with every single request. Obviously not good.
> >> >>> >> > Any suggestions on how to track down where the remember me
> >> >>> >> > problem
> >> >>> >> > is
> >> >>> >> > coming
> >> >>> >> > from - why I'm not getting cookies? I haven't done much of
> >> >>> >> > anything
> >> >>> >> > with
> >> >>> >> > Shiro for months now, and it used to work, so not sure what
> >> >>> >> > happened.
> >> >>> >> > Was it
> >> >>> >> > broken in some recent release that I may be using?
> >> >>> >> > Thanks,
> >> >>> >> > Tauren
> >> >>> >> > On Mon, Apr 19, 2010 at 3:41 AM, Tauren Mills
> >> >>> >> > <yo...@gmail.com>
> >> >>> >> > wrote:
> >> >>> >> >>
> >> >>> >> >> Les,
> >> >>> >> >> Thanks, I'll look into doing this. Are there any examples of
> >> >>> >> >> using
> >> >>> >> >> an
> >> >>> >> >> AuthenticationListener that I could reference?
> >> >>> >> >>
> >> >>> >> >> Tauren
> >> >>> >> >>
> >> >>> >> >> On Fri, Apr 16, 2010 at 9:10 AM, Les Hazlewood
> >> >>> >> >> <lh...@apache.org>
> >> >>> >> >> wrote:
> >> >>> >> >>>
> >> >>> >> >>> Hi Tauren,
> >> >>> >> >>>
> >> >>> >> >>> You could implement an AuthenticationListener - I typically
> >> >>> >> >>> like
> >> >>> >> >>> to do
> >> >>> >> >>> this for these kinds of operations.
> >> >>> >> >>>
> >> >>> >> >>> Since Shiro does not count remember me as a true
> >> >>> >> >>> authentication,
> >> >>> >> >>> the
> >> >>> >> >>> AuthenticationListener will not be triggered for remember me
> >> >>> >> >>> events.
> >> >>> >> >>> To do that you would also need to implement your own
> >> >>> >> >>> RememberMeManager.  Typically subclassing the default one and
> >> >>> >> >>> updating
> >> >>> >> >>> the timestamp in the getRememberedPrincipals method would
> work:
> >> >>> >> >>>
> >> >>> >> >>> @Override
> >> >>> >> >>> public PrincipalCollection getRememberedPrincipals(Map
> >> >>> >> >>> subjectContext)
> >> >>> >> >>> {
> >> >>> >> >>>    PrincipalCollection principals =
> >> >>> >> >>> super.getRememberedPrincipals(subjectContext);
> >> >>> >> >>>    if ( principals != null ) {
> >> >>> >> >>>        int userId = principals.getPrimaryPrincipal();
> >> >>> >> >>>        //update the last login timestamp for user with this
> id
> >> >>> >> >>> here
> >> >>> >> >>>    }
> >> >>> >> >>> }
> >> >>> >> >>>
> >> >>> >> >>> The above method is called only if the current
> Subject/session
> >> >>> >> >>> does
> >> >>> >> >>> not yet have an identity associated with it.
> >> >>> >> >>>
> >> >>> >> >>> The AuthenticationListener + the above overridden method
> should
> >> >>> >> >>> do
> >> >>> >> >>> it!
> >> >>> >> >>>
> >> >>> >> >>> Cheers,
> >> >>> >> >>>
> >> >>> >> >>> Les
> >> >>> >> >>>
> >> >>> >> >>> On Thu, Apr 15, 2010 at 8:37 PM, Tauren Mills
> >> >>> >> >>> <ta...@groovee.com>
> >> >>> >> >>> wrote:
> >> >>> >> >>> > What would be the best way to update properties of a member
> >> >>> >> >>> > on
> >> >>> >> >>> > successful
> >> >>> >> >>> > authentication? Basically, there is a Member.lastLogin
> >> >>> >> >>> > property
> >> >>> >> >>> > that
> >> >>> >> >>> > I
> >> >>> >> >>> > want
> >> >>> >> >>> > updated with the current date every time a member comes
> back
> >> >>> >> >>> > to
> >> >>> >> >>> > a
> >> >>> >> >>> > site
> >> >>> >> >>> > and
> >> >>> >> >>> > logs in.  However, this should also support rememberme
> >> >>> >> >>> > authentications. I
> >> >>> >> >>> > don't necessarily want to update the lastLogin property on
> >> >>> >> >>> > every
> >> >>> >> >>> > single
> >> >>> >> >>> > interaction the user has on the site, just once for each
> >> >>> >> >>> > session.
> >> >>> >> >>> > Is there some technique in Shiro to do this, a callback of
> >> >>> >> >>> > some
> >> >>> >> >>> > sort,
> >> >>> >> >>> > or
> >> >>> >> >>> > some other method? Or should I be doing this in my
> >> >>> >> >>> > application?
> >> >>> >> >>> > Also, I can't seem to view much of the documentation. All
> the
> >> >>> >> >>> > links
> >> >>> >> >>> > on
> >> >>> >> >>> > the
> >> >>> >> >>> > following page require an Apache login. Is it supposed to
> be
> >> >>> >> >>> > this
> >> >>> >> >>> > way?
> >> >>> >> >>> > http://incubator.apache.org/shiro/core.html
> >> >>> >> >>> > Thanks!
> >> >>> >> >>> > Tauren
> >> >>> >> >>> >
> >> >>> >> >>> >
> >> >>> >> >>
> >> >>> >> >
> >> >>> >> >
> >> >>> >
> >> >>> >
> >> >>
> >> >
> >> >
> >
> >
>

Re: Keeping track of user's last login date

Posted by Les Hazlewood <lh...@apache.org>.
Hi Tauren,

The easiest way is to probably use the MethodInvokingFactoryBean for this:

<bean id="myRememberMeManager" class="...">
    <property name="cipherKey" ref="cipherKeyBytes"/>
</bean>

<bean id="cipherKeyBytes"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
   <property name="targetClass" value="org.apache.shiro.codec.Base64"/>
   <property name="targetMethod" value="decode"/>
   <property name="arguments">
     <list>
       <value>your_base64_encoded_string</value>
     </list>
   </property>
</bean>

Cheers,

Les

On Wed, May 12, 2010 at 12:58 PM, Tauren Mills <ta...@tauren.com> wrote:
> Les,
> Thanks, this is helpful. I'd like to use my own custom cipherKey, but I'm
> not using INI configuration. Could you perhaps explain how to configure this
> using Spring instead of INI? I think this too would be useful information to
> go into the wiki.  Here's my current spring config:
>   <bean id="securityManager"
> class="org.apache.shiro.web.DefaultWebSecurityManager">
>     <property name="realm" ref="myRealm"/>
>     <property name="rememberMeManager" ref="myRememberMeManager"/>
>   </bean>
>   <bean name="myRememberMeManager"
> class="com.project.security.MyRememberMeManager"/>
> Thanks!
> Tauren
>
> On Wed, May 12, 2010 at 12:24 PM, Les Hazlewood <lh...@apache.org>
> wrote:
>>
>> Yep, you're exactly right - it is because of the new (more secure)
>> CipherService instances.  I would ignore these warnings - the
>> rememberMe cookie will be deleted and a new correct one will be
>> auto-created the next time they log in (and they click 'remember me'
>> of course).
>>
>> If you didn't want to ignore them and have them just work, you can do 3
>> things:
>>
>> 1.  Configure the RememberMeManager to use the BlowfishCipherService.
>> Prior to the 1.0 release, we defaulted to using the Blowfish
>> algorithm, but most people prefer AES, so now we default to the
>> AesCipherService.
>> 2.  Ensure that the new BlowfishCipherService is using the _exact_
>> same key that was used before.  This is simple if you're using your
>> own cipher key.  It is harder if you were using Shiro's default
>> blowfish key, at which point you would need to look at the old source
>> code to find it.
>> 3.  Ensure that your BlowfishCipherService instance's
>> 'generateInitializationVectors' attribute is set to false.
>>
>> Step 3 makes the encryption less secure and overall 1-3 can be a pain.
>>  I'd recommend just ignoring the warnings for now and let the new
>> cookies replace the old ones if you are ok with that.
>>
>> One thing you might want to try is using your own cipher key with the
>> CipherService instance - it makes it more secure instead of using
>> Shiro's default (which could be discovered by a 3rd party).  To be
>> fair, the encrypted data is just a serialized PrincipalCollection, so
>> if you're not storing sensitive data in the PC, you don't really need
>> to do this.  I still like to do it though in case I ever do need to
>> use an AES Cipher to encrypt something sensitive - then my key is all
>> ready to go.
>>
>> You can do this by doing the following:
>>
>> //AES algorithm only supports key sizes of 128, 192, and 256 bits.
>> //192 and 256 require that the JCE Unlimited Strength
>> //Jurisdiction Policy files to be installed.
>> int keySize = 128;
>> String key = Base64.encode(new
>> AesCipherService().generateNewKey(keySize).getEncoded());
>>
>> //then you can use this key in your shiro config:
>>
>> [main]
>> securityManager.rememberMeManager.cipherKey =
>> your_base64_encoded_string_from_above
>>
>> The configurator will automatically recognize that is a byte array
>> property and Base64 decode the string value into the correct bytes.
>> If you wanted to use Hex encoding instead, make sure you prefix your
>> encoded string with 0x ('zero' 'x'):
>>
>> securityManager.rememberMeManager.cipherKey = 0x123456789ABCDEF
>>
>> which will trigger Hex decoding instead.
>>
>> I know I've rambled on about this, but hopefully this will be indexed
>> by Google and help someone else in the future.  It also gives me a
>> base to use to update the wiki documentation :)
>>
>> Cheers,
>>
>> Les
>>
>> 1.  Ensure that the cipher service is using the same cipher key
>> you could configure your CipherService to set
>> 'generateInitializationVectors' to false, in which case the previou
>>
>> On Wed, May 12, 2010 at 11:08 AM, Tauren Mills <ta...@tauren.com> wrote:
>> > Also, I'm getting the following exception in my logs. I'm assuming that
>> > is
>> > just because people have old cookies with old cyphers, and that once
>> > their
>> > cookies are replaced, I won't see these exceptions anymore. I also
>> > assume
>> > this means that everyone is being forced to log in again since my app
>> > has
>> > been updated with the latest shiro and that no existing rememberme
>> > cookies
>> > will work.  Is this correct?
>> > Thanks,
>> > Tauren
>> > ---
>> >
>> > WARN  - DefaultSecurityManager     - Delegate RememberMeManager instance
>> > of
>> > type [com.project.security.MyRememberMeManager] threw an exception
>> > during
>> > getRememberedPrincipals().
>> > org.apache.shiro.crypto.CryptoException: Unable to execute 'doFinal'
>> > with
>> > cipher instance [javax.crypto.Cipher@5b3bd1c0].
>> > at
>> > org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:465)
>> > at
>> > org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:448)
>> > at
>> >
>> > org.apache.shiro.crypto.JcaCipherService.decrypt(JcaCipherService.java:393)
>> > at
>> >
>> > org.apache.shiro.crypto.JcaCipherService.decrypt(JcaCipherService.java:385)
>> > at
>> >
>> > org.apache.shiro.mgt.AbstractRememberMeManager.decrypt(AbstractRememberMeManager.java:491)
>> > at
>> >
>> > org.apache.shiro.mgt.AbstractRememberMeManager.convertBytesToPrincipals(AbstractRememberMeManager.java:431)
>> > at
>> >
>> > org.apache.shiro.mgt.AbstractRememberMeManager.getRememberedPrincipals(AbstractRememberMeManager.java:398)
>> > at
>> >
>> > com.project.security.MyRememberMeManager.getRememberedPrincipals(MyRememberMeManager.java:21)
>> > at
>> >
>> > org.apache.shiro.mgt.DefaultSecurityManager.getRememberedIdentity(DefaultSecurityManager.java:526)
>> > at
>> >
>> > org.apache.shiro.mgt.DefaultSecurityManager.resolvePrincipals(DefaultSecurityManager.java:403)
>> > at
>> >
>> > org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:320)
>> > at
>> > org.apache.shiro.subject.Subject$Builder.buildSubject(Subject.java:767)
>> > at
>> >
>> > org.apache.shiro.web.subject.WebSubject$Builder.buildWebSubject(WebSubject.java:101)
>> > at org.apache.shiro.web.servlet.ShiroFilter.bind(ShiroFilter.java:540)
>> > at
>> >
>> > org.apache.shiro.web.servlet.ShiroFilter.doFilterInternal(ShiroFilter.java:627)
>> > at
>> >
>> > org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:83)
>> > at
>> >
>> > org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088)
>> > at
>> >
>> > org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
>> > at
>> >
>> > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
>> > at
>> >
>> > org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088)
>> > at
>> > org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
>> > at
>> >
>> > org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
>> > at
>> > org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
>> > at
>> > org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
>> > at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
>> > at
>> > org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
>> > at org.mortbay.jetty.Server.handle(Server.java:324)
>> > at
>> > org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
>> > at
>> >
>> > org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:829)
>> > at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:513)
>> > at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
>> > at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
>> > at
>> >
>> > org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)
>> > at
>> >
>> > org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
>> > Caused by: javax.crypto.BadPaddingException: Given final block not
>> > properly
>> > padded
>> > at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
>> > at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
>> > at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
>> > at javax.crypto.Cipher.doFinal(DashoA13*..)
>> > at
>> > org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:462)
>> > ... 33 more
>> >
>> > On Wed, May 12, 2010 at 9:49 AM, Tauren Mills <ta...@tauren.com> wrote:
>> >>
>> >> Les,
>> >> Thanks for the help.  However, now I'm having a problem
>> >> with getRememberedPrincipals() being called dozens of times per page
>> >> view, causing my "accessed" property to be updated many times, which is
>> >> obviously not ideal.
>> >> I believe this is because my application is running in Jetty, so every
>> >> image, JS, CSS, and other resource is causing a request to be created.
>> >> My
>> >> cookie is set to / since I need it to work for many different paths.
>> >> Any suggestions on how to only update my "accessed" property a single
>> >> time
>> >> per session?  I don't need the property updated with every request,
>> >> just
>> >> when they first access the site for a session is fine.  Basically, the
>> >> property I currently called "accessed" would actually be more
>> >> accurately
>> >> called "lastLogin".
>> >> Below is code if it helps.
>> >> Thanks,
>> >> Tauren
>> >> ---
>> >> public class MyRememberMeManager extends CookieRememberMeManager {
>> >> private MemberService memberService;
>> >>     @Autowired
>> >> public void setMemberService(MemberService memberService) {
>> >> this.memberService = memberService;
>> >> }
>> >> @Override
>> >> public PrincipalCollection getRememberedPrincipals(SubjectContext
>> >> subjectContext) {
>> >> PrincipalCollection principals =
>> >> super.getRememberedPrincipals(subjectContext);
>> >> if ( principals != null ) {
>> >> Long id = (Long) principals.getPrimaryPrincipal();
>> >> memberService.updateAccessed(id);
>> >> }
>> >> return principals;
>> >> }
>> >> }
>> >> // MemberServiceImpl.java
>> >> public void updateAccessed(Long id) {
>> >> updateAccessed(findById(id));
>> >> }
>> >> public void updateAccessed(Member member) {
>> >> member.setAccessed(new Date());
>> >> memberDao.save(member);
>> >> }
>> >>
>> >> // Spring config
>> >>     <bean id="securityManager"
>> >> class="org.apache.shiro.web.DefaultWebSecurityManager">
>> >>       property instead. -->
>> >>         <property name="realm" ref="myRealm"/>
>> >>         <property name="rememberMeManager" ref="myRememberMeManager"/>
>> >>     </bean>
>> >>     <bean name="myRememberMeManager"
>> >> class="com.project.security.MyRememberMeManager"/>
>> >>
>> >> On Tue, May 11, 2010 at 10:11 AM, Les Hazlewood <lh...@apache.org>
>> >> wrote:
>> >>>
>> >>> Hi Tauren,
>> >>>
>> >>> Yes, WebRememberMeManager has been deprecated in favor of the new
>> >>> CookieRememberMeManager which uses a new Cookie property and not the
>> >>> (now deprecated) CookieAttribute concept.  CookieAttribute was complex
>> >>> and confusing.  The new Cookie interface and implementation in
>> >>> comparison are much easier to understand and configure.  So, if you
>> >>> extend CookieRememberMeManager, you should be closely back to where
>> >>> you were when you extended WebRememberMeManager.
>> >>>
>> >>> As for the SubjectContext - it was added within the last two weeks to
>> >>> satisfy a technical requirement: the (now new) SubjectContext.resolve*
>> >>> method behavior was needed in multiple places across more than one OO
>> >>> hierarchy.  So, we either had to copy-n-paste logic (yuck) or
>> >>> consolidate it into a component.  The SubjectContext satisfies this
>> >>> need and will stay in place instead of the raw Map.
>> >>>
>> >>> Also note that for 1.0, we'll be removing all Deprecated classes and
>> >>> methods.  Since we're wrapping up coding issues today (and possibly
>> >>> tomorrow), we'll be deleting them any time now.
>> >>>
>> >>> I hope that helps!
>> >>>
>> >>> Les
>> >>>
>> >>> On Tue, May 11, 2010 at 9:22 AM, Tauren Mills <ta...@tauren.com>
>> >>> wrote:
>> >>> > I'm just getting back to this issue now, and have updated to the
>> >>> > latest
>> >>> > shiro snapshot.
>> >>> > When I started working on this, I had extended WebRememberMeManager,
>> >>> > but it
>> >>> > looks like it is now depricated. What is the recommended approach at
>> >>> > this
>> >>> > time? Should I be directly extending AbstractRememberMeManager?
>> >>> > I also wanted to point out that your example in this thread shows
>> >>> > passing a
>> >>> > Map to getRememberedPrincipals, but in my experience I had to pass a
>> >>> > SubjectContext.  Before I proceed further, I just want to make sure
>> >>> > that I'm
>> >>> > heading down the proper path that will be supported in the future,
>> >>> > and
>> >>> > not
>> >>> > implement something that I'll have to change later.
>> >>> > Thanks!
>> >>> > Tauren
>> >>> >
>> >>> >
>> >>> >
>> >>> >
>> >>> >
>> >>> >
>> >>> > On Mon, Apr 19, 2010 at 12:14 PM, Les Hazlewood
>> >>> > <lh...@apache.org>
>> >>> > wrote:
>> >>> >>
>> >>> >> I committed a change to how cryptography works on Friday - that
>> >>> >> might
>> >>> >> have done something with it (we encrypt principals by default).
>> >>> >> However, all the test cases still passed and I know that we do have
>> >>> >> some test cases around remember me cookies
>> >>> >> (WebRememberMeManagerTest).
>> >>> >>
>> >>> >> Please open a Jira issue in the mean time so we don't lose it.
>> >>> >>  I'll
>> >>> >> try to run the sample web app(s) to see if they exhibit the same
>> >>> >> behavior.
>> >>> >>
>> >>> >> Thanks!
>> >>> >>
>> >>> >> Les
>> >>> >>
>> >>> >> On Mon, Apr 19, 2010 at 10:57 AM, Tauren Mills <yo...@gmail.com>
>> >>> >> wrote:
>> >>> >> > It seems that my remember me function got broken at some point.
>> >>> >> > All
>> >>> >> > of
>> >>> >> > my
>> >>> >> > requests do not have the cookie they used to. I've tried logging
>> >>> >> > off
>> >>> >> > and
>> >>> >> > back in again, but still no cookie.  This is
>> >>> >> > causing getRememberedPrincipals
>> >>> >> > to run with every single request. Obviously not good.
>> >>> >> > Any suggestions on how to track down where the remember me
>> >>> >> > problem
>> >>> >> > is
>> >>> >> > coming
>> >>> >> > from - why I'm not getting cookies? I haven't done much of
>> >>> >> > anything
>> >>> >> > with
>> >>> >> > Shiro for months now, and it used to work, so not sure what
>> >>> >> > happened.
>> >>> >> > Was it
>> >>> >> > broken in some recent release that I may be using?
>> >>> >> > Thanks,
>> >>> >> > Tauren
>> >>> >> > On Mon, Apr 19, 2010 at 3:41 AM, Tauren Mills
>> >>> >> > <yo...@gmail.com>
>> >>> >> > wrote:
>> >>> >> >>
>> >>> >> >> Les,
>> >>> >> >> Thanks, I'll look into doing this. Are there any examples of
>> >>> >> >> using
>> >>> >> >> an
>> >>> >> >> AuthenticationListener that I could reference?
>> >>> >> >>
>> >>> >> >> Tauren
>> >>> >> >>
>> >>> >> >> On Fri, Apr 16, 2010 at 9:10 AM, Les Hazlewood
>> >>> >> >> <lh...@apache.org>
>> >>> >> >> wrote:
>> >>> >> >>>
>> >>> >> >>> Hi Tauren,
>> >>> >> >>>
>> >>> >> >>> You could implement an AuthenticationListener - I typically
>> >>> >> >>> like
>> >>> >> >>> to do
>> >>> >> >>> this for these kinds of operations.
>> >>> >> >>>
>> >>> >> >>> Since Shiro does not count remember me as a true
>> >>> >> >>> authentication,
>> >>> >> >>> the
>> >>> >> >>> AuthenticationListener will not be triggered for remember me
>> >>> >> >>> events.
>> >>> >> >>> To do that you would also need to implement your own
>> >>> >> >>> RememberMeManager.  Typically subclassing the default one and
>> >>> >> >>> updating
>> >>> >> >>> the timestamp in the getRememberedPrincipals method would work:
>> >>> >> >>>
>> >>> >> >>> @Override
>> >>> >> >>> public PrincipalCollection getRememberedPrincipals(Map
>> >>> >> >>> subjectContext)
>> >>> >> >>> {
>> >>> >> >>>    PrincipalCollection principals =
>> >>> >> >>> super.getRememberedPrincipals(subjectContext);
>> >>> >> >>>    if ( principals != null ) {
>> >>> >> >>>        int userId = principals.getPrimaryPrincipal();
>> >>> >> >>>        //update the last login timestamp for user with this id
>> >>> >> >>> here
>> >>> >> >>>    }
>> >>> >> >>> }
>> >>> >> >>>
>> >>> >> >>> The above method is called only if the current Subject/session
>> >>> >> >>> does
>> >>> >> >>> not yet have an identity associated with it.
>> >>> >> >>>
>> >>> >> >>> The AuthenticationListener + the above overridden method should
>> >>> >> >>> do
>> >>> >> >>> it!
>> >>> >> >>>
>> >>> >> >>> Cheers,
>> >>> >> >>>
>> >>> >> >>> Les
>> >>> >> >>>
>> >>> >> >>> On Thu, Apr 15, 2010 at 8:37 PM, Tauren Mills
>> >>> >> >>> <ta...@groovee.com>
>> >>> >> >>> wrote:
>> >>> >> >>> > What would be the best way to update properties of a member
>> >>> >> >>> > on
>> >>> >> >>> > successful
>> >>> >> >>> > authentication? Basically, there is a Member.lastLogin
>> >>> >> >>> > property
>> >>> >> >>> > that
>> >>> >> >>> > I
>> >>> >> >>> > want
>> >>> >> >>> > updated with the current date every time a member comes back
>> >>> >> >>> > to
>> >>> >> >>> > a
>> >>> >> >>> > site
>> >>> >> >>> > and
>> >>> >> >>> > logs in.  However, this should also support rememberme
>> >>> >> >>> > authentications. I
>> >>> >> >>> > don't necessarily want to update the lastLogin property on
>> >>> >> >>> > every
>> >>> >> >>> > single
>> >>> >> >>> > interaction the user has on the site, just once for each
>> >>> >> >>> > session.
>> >>> >> >>> > Is there some technique in Shiro to do this, a callback of
>> >>> >> >>> > some
>> >>> >> >>> > sort,
>> >>> >> >>> > or
>> >>> >> >>> > some other method? Or should I be doing this in my
>> >>> >> >>> > application?
>> >>> >> >>> > Also, I can't seem to view much of the documentation. All the
>> >>> >> >>> > links
>> >>> >> >>> > on
>> >>> >> >>> > the
>> >>> >> >>> > following page require an Apache login. Is it supposed to be
>> >>> >> >>> > this
>> >>> >> >>> > way?
>> >>> >> >>> > http://incubator.apache.org/shiro/core.html
>> >>> >> >>> > Thanks!
>> >>> >> >>> > Tauren
>> >>> >> >>> >
>> >>> >> >>> >
>> >>> >> >>
>> >>> >> >
>> >>> >> >
>> >>> >
>> >>> >
>> >>
>> >
>> >
>
>

Re: Keeping track of user's last login date

Posted by Tauren Mills <ta...@tauren.com>.
Les,

Thanks, this is helpful. I'd like to use my own custom cipherKey, but I'm
not using INI configuration. Could you perhaps explain how to configure this
using Spring instead of INI? I think this too would be useful information to
go into the wiki.  Here's my current spring config:

  <bean id="securityManager"
class="org.apache.shiro.web.DefaultWebSecurityManager">
    <property name="realm" ref="myRealm"/>
    <property name="rememberMeManager" ref="myRememberMeManager"/>
  </bean>

  <bean name="myRememberMeManager"
class="com.project.security.MyRememberMeManager"/>

Thanks!
Tauren


On Wed, May 12, 2010 at 12:24 PM, Les Hazlewood <lh...@apache.org>wrote:

> Yep, you're exactly right - it is because of the new (more secure)
> CipherService instances.  I would ignore these warnings - the
> rememberMe cookie will be deleted and a new correct one will be
> auto-created the next time they log in (and they click 'remember me'
> of course).
>
> If you didn't want to ignore them and have them just work, you can do 3
> things:
>
> 1.  Configure the RememberMeManager to use the BlowfishCipherService.
> Prior to the 1.0 release, we defaulted to using the Blowfish
> algorithm, but most people prefer AES, so now we default to the
> AesCipherService.
> 2.  Ensure that the new BlowfishCipherService is using the _exact_
> same key that was used before.  This is simple if you're using your
> own cipher key.  It is harder if you were using Shiro's default
> blowfish key, at which point you would need to look at the old source
> code to find it.
> 3.  Ensure that your BlowfishCipherService instance's
> 'generateInitializationVectors' attribute is set to false.
>
> Step 3 makes the encryption less secure and overall 1-3 can be a pain.
>  I'd recommend just ignoring the warnings for now and let the new
> cookies replace the old ones if you are ok with that.
>
> One thing you might want to try is using your own cipher key with the
> CipherService instance - it makes it more secure instead of using
> Shiro's default (which could be discovered by a 3rd party).  To be
> fair, the encrypted data is just a serialized PrincipalCollection, so
> if you're not storing sensitive data in the PC, you don't really need
> to do this.  I still like to do it though in case I ever do need to
> use an AES Cipher to encrypt something sensitive - then my key is all
> ready to go.
>
> You can do this by doing the following:
>
> //AES algorithm only supports key sizes of 128, 192, and 256 bits.
> //192 and 256 require that the JCE Unlimited Strength
> //Jurisdiction Policy files to be installed.
> int keySize = 128;
> String key = Base64.encode(new
> AesCipherService().generateNewKey(keySize).getEncoded());
>
> //then you can use this key in your shiro config:
>
> [main]
> securityManager.rememberMeManager.cipherKey =
> your_base64_encoded_string_from_above
>
> The configurator will automatically recognize that is a byte array
> property and Base64 decode the string value into the correct bytes.
> If you wanted to use Hex encoding instead, make sure you prefix your
> encoded string with 0x ('zero' 'x'):
>
> securityManager.rememberMeManager.cipherKey = 0x123456789ABCDEF
>
> which will trigger Hex decoding instead.
>
> I know I've rambled on about this, but hopefully this will be indexed
> by Google and help someone else in the future.  It also gives me a
> base to use to update the wiki documentation :)
>
> Cheers,
>
> Les
>
> 1.  Ensure that the cipher service is using the same cipher key
> you could configure your CipherService to set
> 'generateInitializationVectors' to false, in which case the previou
>
> On Wed, May 12, 2010 at 11:08 AM, Tauren Mills <ta...@tauren.com> wrote:
> > Also, I'm getting the following exception in my logs. I'm assuming that
> is
> > just because people have old cookies with old cyphers, and that once
> their
> > cookies are replaced, I won't see these exceptions anymore. I also assume
> > this means that everyone is being forced to log in again since my app has
> > been updated with the latest shiro and that no existing rememberme
> cookies
> > will work.  Is this correct?
> > Thanks,
> > Tauren
> > ---
> >
> > WARN  - DefaultSecurityManager     - Delegate RememberMeManager instance
> of
> > type [com.project.security.MyRememberMeManager] threw an exception during
> > getRememberedPrincipals().
> > org.apache.shiro.crypto.CryptoException: Unable to execute 'doFinal' with
> > cipher instance [javax.crypto.Cipher@5b3bd1c0].
> > at
> org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:465)
> > at
> org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:448)
> > at
> >
> org.apache.shiro.crypto.JcaCipherService.decrypt(JcaCipherService.java:393)
> > at
> >
> org.apache.shiro.crypto.JcaCipherService.decrypt(JcaCipherService.java:385)
> > at
> >
> org.apache.shiro.mgt.AbstractRememberMeManager.decrypt(AbstractRememberMeManager.java:491)
> > at
> >
> org.apache.shiro.mgt.AbstractRememberMeManager.convertBytesToPrincipals(AbstractRememberMeManager.java:431)
> > at
> >
> org.apache.shiro.mgt.AbstractRememberMeManager.getRememberedPrincipals(AbstractRememberMeManager.java:398)
> > at
> >
> com.project.security.MyRememberMeManager.getRememberedPrincipals(MyRememberMeManager.java:21)
> > at
> >
> org.apache.shiro.mgt.DefaultSecurityManager.getRememberedIdentity(DefaultSecurityManager.java:526)
> > at
> >
> org.apache.shiro.mgt.DefaultSecurityManager.resolvePrincipals(DefaultSecurityManager.java:403)
> > at
> >
> org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:320)
> > at
> org.apache.shiro.subject.Subject$Builder.buildSubject(Subject.java:767)
> > at
> >
> org.apache.shiro.web.subject.WebSubject$Builder.buildWebSubject(WebSubject.java:101)
> > at org.apache.shiro.web.servlet.ShiroFilter.bind(ShiroFilter.java:540)
> > at
> >
> org.apache.shiro.web.servlet.ShiroFilter.doFilterInternal(ShiroFilter.java:627)
> > at
> >
> org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:83)
> > at
> >
> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088)
> > at
> >
> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
> > at
> >
> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
> > at
> >
> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088)
> > at
> org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
> > at
> >
> org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
> > at
> org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
> > at
> org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
> > at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
> > at
> org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
> > at org.mortbay.jetty.Server.handle(Server.java:324)
> > at
> org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
> > at
> >
> org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:829)
> > at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:513)
> > at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
> > at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
> > at
> >
> org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)
> > at
> >
> org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
> > Caused by: javax.crypto.BadPaddingException: Given final block not
> properly
> > padded
> > at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
> > at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
> > at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
> > at javax.crypto.Cipher.doFinal(DashoA13*..)
> > at
> org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:462)
> > ... 33 more
> >
> > On Wed, May 12, 2010 at 9:49 AM, Tauren Mills <ta...@tauren.com> wrote:
> >>
> >> Les,
> >> Thanks for the help.  However, now I'm having a problem
> >> with getRememberedPrincipals() being called dozens of times per page
> >> view, causing my "accessed" property to be updated many times, which is
> >> obviously not ideal.
> >> I believe this is because my application is running in Jetty, so every
> >> image, JS, CSS, and other resource is causing a request to be created.
> My
> >> cookie is set to / since I need it to work for many different paths.
> >> Any suggestions on how to only update my "accessed" property a single
> time
> >> per session?  I don't need the property updated with every request, just
> >> when they first access the site for a session is fine.  Basically, the
> >> property I currently called "accessed" would actually be more accurately
> >> called "lastLogin".
> >> Below is code if it helps.
> >> Thanks,
> >> Tauren
> >> ---
> >> public class MyRememberMeManager extends CookieRememberMeManager {
> >> private MemberService memberService;
> >>     @Autowired
> >> public void setMemberService(MemberService memberService) {
> >> this.memberService = memberService;
> >> }
> >> @Override
> >> public PrincipalCollection getRememberedPrincipals(SubjectContext
> >> subjectContext) {
> >> PrincipalCollection principals =
> >> super.getRememberedPrincipals(subjectContext);
> >> if ( principals != null ) {
> >> Long id = (Long) principals.getPrimaryPrincipal();
> >> memberService.updateAccessed(id);
> >> }
> >> return principals;
> >> }
> >> }
> >> // MemberServiceImpl.java
> >> public void updateAccessed(Long id) {
> >> updateAccessed(findById(id));
> >> }
> >> public void updateAccessed(Member member) {
> >> member.setAccessed(new Date());
> >> memberDao.save(member);
> >> }
> >>
> >> // Spring config
> >>     <bean id="securityManager"
> >> class="org.apache.shiro.web.DefaultWebSecurityManager">
> >>       property instead. -->
> >>         <property name="realm" ref="myRealm"/>
> >>         <property name="rememberMeManager" ref="myRememberMeManager"/>
> >>     </bean>
> >>     <bean name="myRememberMeManager"
> >> class="com.project.security.MyRememberMeManager"/>
> >>
> >> On Tue, May 11, 2010 at 10:11 AM, Les Hazlewood <lh...@apache.org>
> >> wrote:
> >>>
> >>> Hi Tauren,
> >>>
> >>> Yes, WebRememberMeManager has been deprecated in favor of the new
> >>> CookieRememberMeManager which uses a new Cookie property and not the
> >>> (now deprecated) CookieAttribute concept.  CookieAttribute was complex
> >>> and confusing.  The new Cookie interface and implementation in
> >>> comparison are much easier to understand and configure.  So, if you
> >>> extend CookieRememberMeManager, you should be closely back to where
> >>> you were when you extended WebRememberMeManager.
> >>>
> >>> As for the SubjectContext - it was added within the last two weeks to
> >>> satisfy a technical requirement: the (now new) SubjectContext.resolve*
> >>> method behavior was needed in multiple places across more than one OO
> >>> hierarchy.  So, we either had to copy-n-paste logic (yuck) or
> >>> consolidate it into a component.  The SubjectContext satisfies this
> >>> need and will stay in place instead of the raw Map.
> >>>
> >>> Also note that for 1.0, we'll be removing all Deprecated classes and
> >>> methods.  Since we're wrapping up coding issues today (and possibly
> >>> tomorrow), we'll be deleting them any time now.
> >>>
> >>> I hope that helps!
> >>>
> >>> Les
> >>>
> >>> On Tue, May 11, 2010 at 9:22 AM, Tauren Mills <ta...@tauren.com>
> wrote:
> >>> > I'm just getting back to this issue now, and have updated to the
> latest
> >>> > shiro snapshot.
> >>> > When I started working on this, I had extended WebRememberMeManager,
> >>> > but it
> >>> > looks like it is now depricated. What is the recommended approach at
> >>> > this
> >>> > time? Should I be directly extending AbstractRememberMeManager?
> >>> > I also wanted to point out that your example in this thread shows
> >>> > passing a
> >>> > Map to getRememberedPrincipals, but in my experience I had to pass a
> >>> > SubjectContext.  Before I proceed further, I just want to make sure
> >>> > that I'm
> >>> > heading down the proper path that will be supported in the future,
> and
> >>> > not
> >>> > implement something that I'll have to change later.
> >>> > Thanks!
> >>> > Tauren
> >>> >
> >>> >
> >>> >
> >>> >
> >>> >
> >>> >
> >>> > On Mon, Apr 19, 2010 at 12:14 PM, Les Hazlewood <
> lhazlewood@apache.org>
> >>> > wrote:
> >>> >>
> >>> >> I committed a change to how cryptography works on Friday - that
> might
> >>> >> have done something with it (we encrypt principals by default).
> >>> >> However, all the test cases still passed and I know that we do have
> >>> >> some test cases around remember me cookies
> (WebRememberMeManagerTest).
> >>> >>
> >>> >> Please open a Jira issue in the mean time so we don't lose it.  I'll
> >>> >> try to run the sample web app(s) to see if they exhibit the same
> >>> >> behavior.
> >>> >>
> >>> >> Thanks!
> >>> >>
> >>> >> Les
> >>> >>
> >>> >> On Mon, Apr 19, 2010 at 10:57 AM, Tauren Mills <yo...@gmail.com>
> >>> >> wrote:
> >>> >> > It seems that my remember me function got broken at some point.
> All
> >>> >> > of
> >>> >> > my
> >>> >> > requests do not have the cookie they used to. I've tried logging
> off
> >>> >> > and
> >>> >> > back in again, but still no cookie.  This is
> >>> >> > causing getRememberedPrincipals
> >>> >> > to run with every single request. Obviously not good.
> >>> >> > Any suggestions on how to track down where the remember me problem
> >>> >> > is
> >>> >> > coming
> >>> >> > from - why I'm not getting cookies? I haven't done much of
> anything
> >>> >> > with
> >>> >> > Shiro for months now, and it used to work, so not sure what
> >>> >> > happened.
> >>> >> > Was it
> >>> >> > broken in some recent release that I may be using?
> >>> >> > Thanks,
> >>> >> > Tauren
> >>> >> > On Mon, Apr 19, 2010 at 3:41 AM, Tauren Mills <yowzator@gmail.com
> >
> >>> >> > wrote:
> >>> >> >>
> >>> >> >> Les,
> >>> >> >> Thanks, I'll look into doing this. Are there any examples of
> using
> >>> >> >> an
> >>> >> >> AuthenticationListener that I could reference?
> >>> >> >>
> >>> >> >> Tauren
> >>> >> >>
> >>> >> >> On Fri, Apr 16, 2010 at 9:10 AM, Les Hazlewood
> >>> >> >> <lh...@apache.org>
> >>> >> >> wrote:
> >>> >> >>>
> >>> >> >>> Hi Tauren,
> >>> >> >>>
> >>> >> >>> You could implement an AuthenticationListener - I typically like
> >>> >> >>> to do
> >>> >> >>> this for these kinds of operations.
> >>> >> >>>
> >>> >> >>> Since Shiro does not count remember me as a true authentication,
> >>> >> >>> the
> >>> >> >>> AuthenticationListener will not be triggered for remember me
> >>> >> >>> events.
> >>> >> >>> To do that you would also need to implement your own
> >>> >> >>> RememberMeManager.  Typically subclassing the default one and
> >>> >> >>> updating
> >>> >> >>> the timestamp in the getRememberedPrincipals method would work:
> >>> >> >>>
> >>> >> >>> @Override
> >>> >> >>> public PrincipalCollection getRememberedPrincipals(Map
> >>> >> >>> subjectContext)
> >>> >> >>> {
> >>> >> >>>    PrincipalCollection principals =
> >>> >> >>> super.getRememberedPrincipals(subjectContext);
> >>> >> >>>    if ( principals != null ) {
> >>> >> >>>        int userId = principals.getPrimaryPrincipal();
> >>> >> >>>        //update the last login timestamp for user with this id
> >>> >> >>> here
> >>> >> >>>    }
> >>> >> >>> }
> >>> >> >>>
> >>> >> >>> The above method is called only if the current Subject/session
> >>> >> >>> does
> >>> >> >>> not yet have an identity associated with it.
> >>> >> >>>
> >>> >> >>> The AuthenticationListener + the above overridden method should
> do
> >>> >> >>> it!
> >>> >> >>>
> >>> >> >>> Cheers,
> >>> >> >>>
> >>> >> >>> Les
> >>> >> >>>
> >>> >> >>> On Thu, Apr 15, 2010 at 8:37 PM, Tauren Mills <
> tauren@groovee.com>
> >>> >> >>> wrote:
> >>> >> >>> > What would be the best way to update properties of a member on
> >>> >> >>> > successful
> >>> >> >>> > authentication? Basically, there is a Member.lastLogin
> property
> >>> >> >>> > that
> >>> >> >>> > I
> >>> >> >>> > want
> >>> >> >>> > updated with the current date every time a member comes back
> to
> >>> >> >>> > a
> >>> >> >>> > site
> >>> >> >>> > and
> >>> >> >>> > logs in.  However, this should also support rememberme
> >>> >> >>> > authentications. I
> >>> >> >>> > don't necessarily want to update the lastLogin property on
> every
> >>> >> >>> > single
> >>> >> >>> > interaction the user has on the site, just once for each
> >>> >> >>> > session.
> >>> >> >>> > Is there some technique in Shiro to do this, a callback of
> some
> >>> >> >>> > sort,
> >>> >> >>> > or
> >>> >> >>> > some other method? Or should I be doing this in my
> application?
> >>> >> >>> > Also, I can't seem to view much of the documentation. All the
> >>> >> >>> > links
> >>> >> >>> > on
> >>> >> >>> > the
> >>> >> >>> > following page require an Apache login. Is it supposed to be
> >>> >> >>> > this
> >>> >> >>> > way?
> >>> >> >>> > http://incubator.apache.org/shiro/core.html
> >>> >> >>> > Thanks!
> >>> >> >>> > Tauren
> >>> >> >>> >
> >>> >> >>> >
> >>> >> >>
> >>> >> >
> >>> >> >
> >>> >
> >>> >
> >>
> >
> >
>

Re: Keeping track of user's last login date

Posted by Les Hazlewood <lh...@apache.org>.
Yep, you're exactly right - it is because of the new (more secure)
CipherService instances.  I would ignore these warnings - the
rememberMe cookie will be deleted and a new correct one will be
auto-created the next time they log in (and they click 'remember me'
of course).

If you didn't want to ignore them and have them just work, you can do 3 things:

1.  Configure the RememberMeManager to use the BlowfishCipherService.
Prior to the 1.0 release, we defaulted to using the Blowfish
algorithm, but most people prefer AES, so now we default to the
AesCipherService.
2.  Ensure that the new BlowfishCipherService is using the _exact_
same key that was used before.  This is simple if you're using your
own cipher key.  It is harder if you were using Shiro's default
blowfish key, at which point you would need to look at the old source
code to find it.
3.  Ensure that your BlowfishCipherService instance's
'generateInitializationVectors' attribute is set to false.

Step 3 makes the encryption less secure and overall 1-3 can be a pain.
 I'd recommend just ignoring the warnings for now and let the new
cookies replace the old ones if you are ok with that.

One thing you might want to try is using your own cipher key with the
CipherService instance - it makes it more secure instead of using
Shiro's default (which could be discovered by a 3rd party).  To be
fair, the encrypted data is just a serialized PrincipalCollection, so
if you're not storing sensitive data in the PC, you don't really need
to do this.  I still like to do it though in case I ever do need to
use an AES Cipher to encrypt something sensitive - then my key is all
ready to go.

You can do this by doing the following:

//AES algorithm only supports key sizes of 128, 192, and 256 bits.
//192 and 256 require that the JCE Unlimited Strength
//Jurisdiction Policy files to be installed.
int keySize = 128;
String key = Base64.encode(new
AesCipherService().generateNewKey(keySize).getEncoded());

//then you can use this key in your shiro config:

[main]
securityManager.rememberMeManager.cipherKey =
your_base64_encoded_string_from_above

The configurator will automatically recognize that is a byte array
property and Base64 decode the string value into the correct bytes.
If you wanted to use Hex encoding instead, make sure you prefix your
encoded string with 0x ('zero' 'x'):

securityManager.rememberMeManager.cipherKey = 0x123456789ABCDEF

which will trigger Hex decoding instead.

I know I've rambled on about this, but hopefully this will be indexed
by Google and help someone else in the future.  It also gives me a
base to use to update the wiki documentation :)

Cheers,

Les

1.  Ensure that the cipher service is using the same cipher key
you could configure your CipherService to set
'generateInitializationVectors' to false, in which case the previou

On Wed, May 12, 2010 at 11:08 AM, Tauren Mills <ta...@tauren.com> wrote:
> Also, I'm getting the following exception in my logs. I'm assuming that is
> just because people have old cookies with old cyphers, and that once their
> cookies are replaced, I won't see these exceptions anymore. I also assume
> this means that everyone is being forced to log in again since my app has
> been updated with the latest shiro and that no existing rememberme cookies
> will work.  Is this correct?
> Thanks,
> Tauren
> ---
>
> WARN  - DefaultSecurityManager     - Delegate RememberMeManager instance of
> type [com.project.security.MyRememberMeManager] threw an exception during
> getRememberedPrincipals().
> org.apache.shiro.crypto.CryptoException: Unable to execute 'doFinal' with
> cipher instance [javax.crypto.Cipher@5b3bd1c0].
> at org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:465)
> at org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:448)
> at
> org.apache.shiro.crypto.JcaCipherService.decrypt(JcaCipherService.java:393)
> at
> org.apache.shiro.crypto.JcaCipherService.decrypt(JcaCipherService.java:385)
> at
> org.apache.shiro.mgt.AbstractRememberMeManager.decrypt(AbstractRememberMeManager.java:491)
> at
> org.apache.shiro.mgt.AbstractRememberMeManager.convertBytesToPrincipals(AbstractRememberMeManager.java:431)
> at
> org.apache.shiro.mgt.AbstractRememberMeManager.getRememberedPrincipals(AbstractRememberMeManager.java:398)
> at
> com.project.security.MyRememberMeManager.getRememberedPrincipals(MyRememberMeManager.java:21)
> at
> org.apache.shiro.mgt.DefaultSecurityManager.getRememberedIdentity(DefaultSecurityManager.java:526)
> at
> org.apache.shiro.mgt.DefaultSecurityManager.resolvePrincipals(DefaultSecurityManager.java:403)
> at
> org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:320)
> at org.apache.shiro.subject.Subject$Builder.buildSubject(Subject.java:767)
> at
> org.apache.shiro.web.subject.WebSubject$Builder.buildWebSubject(WebSubject.java:101)
> at org.apache.shiro.web.servlet.ShiroFilter.bind(ShiroFilter.java:540)
> at
> org.apache.shiro.web.servlet.ShiroFilter.doFilterInternal(ShiroFilter.java:627)
> at
> org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:83)
> at
> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088)
> at
> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
> at
> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
> at
> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088)
> at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
> at
> org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
> at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
> at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
> at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
> at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
> at org.mortbay.jetty.Server.handle(Server.java:324)
> at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
> at
> org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:829)
> at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:513)
> at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
> at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
> at
> org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)
> at
> org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
> Caused by: javax.crypto.BadPaddingException: Given final block not properly
> padded
> at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
> at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
> at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
> at javax.crypto.Cipher.doFinal(DashoA13*..)
> at org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:462)
> ... 33 more
>
> On Wed, May 12, 2010 at 9:49 AM, Tauren Mills <ta...@tauren.com> wrote:
>>
>> Les,
>> Thanks for the help.  However, now I'm having a problem
>> with getRememberedPrincipals() being called dozens of times per page
>> view, causing my "accessed" property to be updated many times, which is
>> obviously not ideal.
>> I believe this is because my application is running in Jetty, so every
>> image, JS, CSS, and other resource is causing a request to be created. My
>> cookie is set to / since I need it to work for many different paths.
>> Any suggestions on how to only update my "accessed" property a single time
>> per session?  I don't need the property updated with every request, just
>> when they first access the site for a session is fine.  Basically, the
>> property I currently called "accessed" would actually be more accurately
>> called "lastLogin".
>> Below is code if it helps.
>> Thanks,
>> Tauren
>> ---
>> public class MyRememberMeManager extends CookieRememberMeManager {
>> private MemberService memberService;
>>     @Autowired
>> public void setMemberService(MemberService memberService) {
>> this.memberService = memberService;
>> }
>> @Override
>> public PrincipalCollection getRememberedPrincipals(SubjectContext
>> subjectContext) {
>> PrincipalCollection principals =
>> super.getRememberedPrincipals(subjectContext);
>> if ( principals != null ) {
>> Long id = (Long) principals.getPrimaryPrincipal();
>> memberService.updateAccessed(id);
>> }
>> return principals;
>> }
>> }
>> // MemberServiceImpl.java
>> public void updateAccessed(Long id) {
>> updateAccessed(findById(id));
>> }
>> public void updateAccessed(Member member) {
>> member.setAccessed(new Date());
>> memberDao.save(member);
>> }
>>
>> // Spring config
>>     <bean id="securityManager"
>> class="org.apache.shiro.web.DefaultWebSecurityManager">
>>       property instead. -->
>>         <property name="realm" ref="myRealm"/>
>>         <property name="rememberMeManager" ref="myRememberMeManager"/>
>>     </bean>
>>     <bean name="myRememberMeManager"
>> class="com.project.security.MyRememberMeManager"/>
>>
>> On Tue, May 11, 2010 at 10:11 AM, Les Hazlewood <lh...@apache.org>
>> wrote:
>>>
>>> Hi Tauren,
>>>
>>> Yes, WebRememberMeManager has been deprecated in favor of the new
>>> CookieRememberMeManager which uses a new Cookie property and not the
>>> (now deprecated) CookieAttribute concept.  CookieAttribute was complex
>>> and confusing.  The new Cookie interface and implementation in
>>> comparison are much easier to understand and configure.  So, if you
>>> extend CookieRememberMeManager, you should be closely back to where
>>> you were when you extended WebRememberMeManager.
>>>
>>> As for the SubjectContext - it was added within the last two weeks to
>>> satisfy a technical requirement: the (now new) SubjectContext.resolve*
>>> method behavior was needed in multiple places across more than one OO
>>> hierarchy.  So, we either had to copy-n-paste logic (yuck) or
>>> consolidate it into a component.  The SubjectContext satisfies this
>>> need and will stay in place instead of the raw Map.
>>>
>>> Also note that for 1.0, we'll be removing all Deprecated classes and
>>> methods.  Since we're wrapping up coding issues today (and possibly
>>> tomorrow), we'll be deleting them any time now.
>>>
>>> I hope that helps!
>>>
>>> Les
>>>
>>> On Tue, May 11, 2010 at 9:22 AM, Tauren Mills <ta...@tauren.com> wrote:
>>> > I'm just getting back to this issue now, and have updated to the latest
>>> > shiro snapshot.
>>> > When I started working on this, I had extended WebRememberMeManager,
>>> > but it
>>> > looks like it is now depricated. What is the recommended approach at
>>> > this
>>> > time? Should I be directly extending AbstractRememberMeManager?
>>> > I also wanted to point out that your example in this thread shows
>>> > passing a
>>> > Map to getRememberedPrincipals, but in my experience I had to pass a
>>> > SubjectContext.  Before I proceed further, I just want to make sure
>>> > that I'm
>>> > heading down the proper path that will be supported in the future, and
>>> > not
>>> > implement something that I'll have to change later.
>>> > Thanks!
>>> > Tauren
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> > On Mon, Apr 19, 2010 at 12:14 PM, Les Hazlewood <lh...@apache.org>
>>> > wrote:
>>> >>
>>> >> I committed a change to how cryptography works on Friday - that might
>>> >> have done something with it (we encrypt principals by default).
>>> >> However, all the test cases still passed and I know that we do have
>>> >> some test cases around remember me cookies (WebRememberMeManagerTest).
>>> >>
>>> >> Please open a Jira issue in the mean time so we don't lose it.  I'll
>>> >> try to run the sample web app(s) to see if they exhibit the same
>>> >> behavior.
>>> >>
>>> >> Thanks!
>>> >>
>>> >> Les
>>> >>
>>> >> On Mon, Apr 19, 2010 at 10:57 AM, Tauren Mills <yo...@gmail.com>
>>> >> wrote:
>>> >> > It seems that my remember me function got broken at some point. All
>>> >> > of
>>> >> > my
>>> >> > requests do not have the cookie they used to. I've tried logging off
>>> >> > and
>>> >> > back in again, but still no cookie.  This is
>>> >> > causing getRememberedPrincipals
>>> >> > to run with every single request. Obviously not good.
>>> >> > Any suggestions on how to track down where the remember me problem
>>> >> > is
>>> >> > coming
>>> >> > from - why I'm not getting cookies? I haven't done much of anything
>>> >> > with
>>> >> > Shiro for months now, and it used to work, so not sure what
>>> >> > happened.
>>> >> > Was it
>>> >> > broken in some recent release that I may be using?
>>> >> > Thanks,
>>> >> > Tauren
>>> >> > On Mon, Apr 19, 2010 at 3:41 AM, Tauren Mills <yo...@gmail.com>
>>> >> > wrote:
>>> >> >>
>>> >> >> Les,
>>> >> >> Thanks, I'll look into doing this. Are there any examples of using
>>> >> >> an
>>> >> >> AuthenticationListener that I could reference?
>>> >> >>
>>> >> >> Tauren
>>> >> >>
>>> >> >> On Fri, Apr 16, 2010 at 9:10 AM, Les Hazlewood
>>> >> >> <lh...@apache.org>
>>> >> >> wrote:
>>> >> >>>
>>> >> >>> Hi Tauren,
>>> >> >>>
>>> >> >>> You could implement an AuthenticationListener - I typically like
>>> >> >>> to do
>>> >> >>> this for these kinds of operations.
>>> >> >>>
>>> >> >>> Since Shiro does not count remember me as a true authentication,
>>> >> >>> the
>>> >> >>> AuthenticationListener will not be triggered for remember me
>>> >> >>> events.
>>> >> >>> To do that you would also need to implement your own
>>> >> >>> RememberMeManager.  Typically subclassing the default one and
>>> >> >>> updating
>>> >> >>> the timestamp in the getRememberedPrincipals method would work:
>>> >> >>>
>>> >> >>> @Override
>>> >> >>> public PrincipalCollection getRememberedPrincipals(Map
>>> >> >>> subjectContext)
>>> >> >>> {
>>> >> >>>    PrincipalCollection principals =
>>> >> >>> super.getRememberedPrincipals(subjectContext);
>>> >> >>>    if ( principals != null ) {
>>> >> >>>        int userId = principals.getPrimaryPrincipal();
>>> >> >>>        //update the last login timestamp for user with this id
>>> >> >>> here
>>> >> >>>    }
>>> >> >>> }
>>> >> >>>
>>> >> >>> The above method is called only if the current Subject/session
>>> >> >>> does
>>> >> >>> not yet have an identity associated with it.
>>> >> >>>
>>> >> >>> The AuthenticationListener + the above overridden method should do
>>> >> >>> it!
>>> >> >>>
>>> >> >>> Cheers,
>>> >> >>>
>>> >> >>> Les
>>> >> >>>
>>> >> >>> On Thu, Apr 15, 2010 at 8:37 PM, Tauren Mills <ta...@groovee.com>
>>> >> >>> wrote:
>>> >> >>> > What would be the best way to update properties of a member on
>>> >> >>> > successful
>>> >> >>> > authentication? Basically, there is a Member.lastLogin property
>>> >> >>> > that
>>> >> >>> > I
>>> >> >>> > want
>>> >> >>> > updated with the current date every time a member comes back to
>>> >> >>> > a
>>> >> >>> > site
>>> >> >>> > and
>>> >> >>> > logs in.  However, this should also support rememberme
>>> >> >>> > authentications. I
>>> >> >>> > don't necessarily want to update the lastLogin property on every
>>> >> >>> > single
>>> >> >>> > interaction the user has on the site, just once for each
>>> >> >>> > session.
>>> >> >>> > Is there some technique in Shiro to do this, a callback of some
>>> >> >>> > sort,
>>> >> >>> > or
>>> >> >>> > some other method? Or should I be doing this in my application?
>>> >> >>> > Also, I can't seem to view much of the documentation. All the
>>> >> >>> > links
>>> >> >>> > on
>>> >> >>> > the
>>> >> >>> > following page require an Apache login. Is it supposed to be
>>> >> >>> > this
>>> >> >>> > way?
>>> >> >>> > http://incubator.apache.org/shiro/core.html
>>> >> >>> > Thanks!
>>> >> >>> > Tauren
>>> >> >>> >
>>> >> >>> >
>>> >> >>
>>> >> >
>>> >> >
>>> >
>>> >
>>
>
>

Re: Keeping track of user's last login date

Posted by Tauren Mills <ta...@tauren.com>.
Also, I'm getting the following exception in my logs. I'm assuming that is
just because people have old cookies with old cyphers, and that once their
cookies are replaced, I won't see these exceptions anymore. I also assume
this means that everyone is being forced to log in again since my app has
been updated with the latest shiro and that no existing rememberme cookies
will work.  Is this correct?

Thanks,
Tauren

---

WARN  - DefaultSecurityManager     - Delegate RememberMeManager instance of
type [com.project.security.MyRememberMeManager] threw an exception during
getRememberedPrincipals().
org.apache.shiro.crypto.CryptoException: Unable to execute 'doFinal' with
cipher instance [javax.crypto.Cipher@5b3bd1c0].
at org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:465)
at org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:448)
at
org.apache.shiro.crypto.JcaCipherService.decrypt(JcaCipherService.java:393)
at
org.apache.shiro.crypto.JcaCipherService.decrypt(JcaCipherService.java:385)
at
org.apache.shiro.mgt.AbstractRememberMeManager.decrypt(AbstractRememberMeManager.java:491)
at
org.apache.shiro.mgt.AbstractRememberMeManager.convertBytesToPrincipals(AbstractRememberMeManager.java:431)
at
org.apache.shiro.mgt.AbstractRememberMeManager.getRememberedPrincipals(AbstractRememberMeManager.java:398)
at
com.project.security.MyRememberMeManager.getRememberedPrincipals(MyRememberMeManager.java:21)
at
org.apache.shiro.mgt.DefaultSecurityManager.getRememberedIdentity(DefaultSecurityManager.java:526)
at
org.apache.shiro.mgt.DefaultSecurityManager.resolvePrincipals(DefaultSecurityManager.java:403)
at
org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:320)
at org.apache.shiro.subject.Subject$Builder.buildSubject(Subject.java:767)
at
org.apache.shiro.web.subject.WebSubject$Builder.buildWebSubject(WebSubject.java:101)
at org.apache.shiro.web.servlet.ShiroFilter.bind(ShiroFilter.java:540)
at
org.apache.shiro.web.servlet.ShiroFilter.doFilterInternal(ShiroFilter.java:627)
at
org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:83)
at
org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088)
at
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at
org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
at
org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:324)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
at
org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:829)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:513)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
at
org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)
at
org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
Caused by: javax.crypto.BadPaddingException: Given final block not properly
padded
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:462)
... 33 more


On Wed, May 12, 2010 at 9:49 AM, Tauren Mills <ta...@tauren.com> wrote:

> Les,
>
> Thanks for the help.  However, now I'm having a problem
> with getRememberedPrincipals() being called dozens of times per page
> view, causing my "accessed" property to be updated many times, which is
> obviously not ideal.
>
> I believe this is because my application is running in Jetty, so every
> image, JS, CSS, and other resource is causing a request to be created. My
> cookie is set to / since I need it to work for many different paths.
>
> Any suggestions on how to only update my "accessed" property a single time
> per session?  I don't need the property updated with every request, just
> when they first access the site for a session is fine.  Basically, the
> property I currently called "accessed" would actually be more accurately
> called "lastLogin".
>
> Below is code if it helps.
>
> Thanks,
> Tauren
>
> ---
>
> public class MyRememberMeManager extends CookieRememberMeManager {
>
> private MemberService memberService;
>
>     @Autowired
> public void setMemberService(MemberService memberService) {
>  this.memberService = memberService;
> }
>
> @Override
>  public PrincipalCollection getRememberedPrincipals(SubjectContext
> subjectContext) {
> PrincipalCollection principals =
> super.getRememberedPrincipals(subjectContext);
>  if ( principals != null ) {
> Long id = (Long) principals.getPrimaryPrincipal();
>  memberService.updateAccessed(id);
> }
> return principals;
>  }
> }
>
> // MemberServiceImpl.java
>
>  public void updateAccessed(Long id) {
> updateAccessed(findById(id));
>  }
>
> public void updateAccessed(Member member) {
> member.setAccessed(new Date());
>  memberDao.save(member);
> }
>
>
> // Spring config
>
>     <bean id="securityManager"
> class="org.apache.shiro.web.DefaultWebSecurityManager">
>       property instead. -->
>         <property name="realm" ref="myRealm"/>
>         <property name="rememberMeManager" ref="myRememberMeManager"/>
>     </bean>
>
>     <bean name="myRememberMeManager"
> class="com.project.security.MyRememberMeManager"/>
>
>
> On Tue, May 11, 2010 at 10:11 AM, Les Hazlewood <lh...@apache.org>wrote:
>
>> Hi Tauren,
>>
>> Yes, WebRememberMeManager has been deprecated in favor of the new
>> CookieRememberMeManager which uses a new Cookie property and not the
>> (now deprecated) CookieAttribute concept.  CookieAttribute was complex
>> and confusing.  The new Cookie interface and implementation in
>> comparison are much easier to understand and configure.  So, if you
>> extend CookieRememberMeManager, you should be closely back to where
>> you were when you extended WebRememberMeManager.
>>
>> As for the SubjectContext - it was added within the last two weeks to
>> satisfy a technical requirement: the (now new) SubjectContext.resolve*
>> method behavior was needed in multiple places across more than one OO
>> hierarchy.  So, we either had to copy-n-paste logic (yuck) or
>> consolidate it into a component.  The SubjectContext satisfies this
>> need and will stay in place instead of the raw Map.
>>
>> Also note that for 1.0, we'll be removing all Deprecated classes and
>> methods.  Since we're wrapping up coding issues today (and possibly
>> tomorrow), we'll be deleting them any time now.
>>
>> I hope that helps!
>>
>> Les
>>
>> On Tue, May 11, 2010 at 9:22 AM, Tauren Mills <ta...@tauren.com> wrote:
>> > I'm just getting back to this issue now, and have updated to the latest
>> > shiro snapshot.
>> > When I started working on this, I had extended WebRememberMeManager, but
>> it
>> > looks like it is now depricated. What is the recommended approach at
>> this
>> > time? Should I be directly extending AbstractRememberMeManager?
>> > I also wanted to point out that your example in this thread shows
>> passing a
>> > Map to getRememberedPrincipals, but in my experience I had to pass a
>> > SubjectContext.  Before I proceed further, I just want to make sure that
>> I'm
>> > heading down the proper path that will be supported in the future, and
>> not
>> > implement something that I'll have to change later.
>> > Thanks!
>> > Tauren
>> >
>> >
>> >
>> >
>> >
>> >
>> > On Mon, Apr 19, 2010 at 12:14 PM, Les Hazlewood <lh...@apache.org>
>> > wrote:
>> >>
>> >> I committed a change to how cryptography works on Friday - that might
>> >> have done something with it (we encrypt principals by default).
>> >> However, all the test cases still passed and I know that we do have
>> >> some test cases around remember me cookies (WebRememberMeManagerTest).
>> >>
>> >> Please open a Jira issue in the mean time so we don't lose it.  I'll
>> >> try to run the sample web app(s) to see if they exhibit the same
>> >> behavior.
>> >>
>> >> Thanks!
>> >>
>> >> Les
>> >>
>> >> On Mon, Apr 19, 2010 at 10:57 AM, Tauren Mills <yo...@gmail.com>
>> wrote:
>> >> > It seems that my remember me function got broken at some point. All
>> of
>> >> > my
>> >> > requests do not have the cookie they used to. I've tried logging off
>> and
>> >> > back in again, but still no cookie.  This is
>> >> > causing getRememberedPrincipals
>> >> > to run with every single request. Obviously not good.
>> >> > Any suggestions on how to track down where the remember me problem is
>> >> > coming
>> >> > from - why I'm not getting cookies? I haven't done much of anything
>> with
>> >> > Shiro for months now, and it used to work, so not sure what happened.
>> >> > Was it
>> >> > broken in some recent release that I may be using?
>> >> > Thanks,
>> >> > Tauren
>> >> > On Mon, Apr 19, 2010 at 3:41 AM, Tauren Mills <yo...@gmail.com>
>> >> > wrote:
>> >> >>
>> >> >> Les,
>> >> >> Thanks, I'll look into doing this. Are there any examples of using
>> an
>> >> >> AuthenticationListener that I could reference?
>> >> >>
>> >> >> Tauren
>> >> >>
>> >> >> On Fri, Apr 16, 2010 at 9:10 AM, Les Hazlewood <
>> lhazlewood@apache.org>
>> >> >> wrote:
>> >> >>>
>> >> >>> Hi Tauren,
>> >> >>>
>> >> >>> You could implement an AuthenticationListener - I typically like to
>> do
>> >> >>> this for these kinds of operations.
>> >> >>>
>> >> >>> Since Shiro does not count remember me as a true authentication,
>> the
>> >> >>> AuthenticationListener will not be triggered for remember me
>> events.
>> >> >>> To do that you would also need to implement your own
>> >> >>> RememberMeManager.  Typically subclassing the default one and
>> updating
>> >> >>> the timestamp in the getRememberedPrincipals method would work:
>> >> >>>
>> >> >>> @Override
>> >> >>> public PrincipalCollection getRememberedPrincipals(Map
>> subjectContext)
>> >> >>> {
>> >> >>>    PrincipalCollection principals =
>> >> >>> super.getRememberedPrincipals(subjectContext);
>> >> >>>    if ( principals != null ) {
>> >> >>>        int userId = principals.getPrimaryPrincipal();
>> >> >>>        //update the last login timestamp for user with this id here
>> >> >>>    }
>> >> >>> }
>> >> >>>
>> >> >>> The above method is called only if the current Subject/session does
>> >> >>> not yet have an identity associated with it.
>> >> >>>
>> >> >>> The AuthenticationListener + the above overridden method should do
>> it!
>> >> >>>
>> >> >>> Cheers,
>> >> >>>
>> >> >>> Les
>> >> >>>
>> >> >>> On Thu, Apr 15, 2010 at 8:37 PM, Tauren Mills <ta...@groovee.com>
>> >> >>> wrote:
>> >> >>> > What would be the best way to update properties of a member on
>> >> >>> > successful
>> >> >>> > authentication? Basically, there is a Member.lastLogin property
>> that
>> >> >>> > I
>> >> >>> > want
>> >> >>> > updated with the current date every time a member comes back to a
>> >> >>> > site
>> >> >>> > and
>> >> >>> > logs in.  However, this should also support rememberme
>> >> >>> > authentications. I
>> >> >>> > don't necessarily want to update the lastLogin property on every
>> >> >>> > single
>> >> >>> > interaction the user has on the site, just once for each session.
>> >> >>> > Is there some technique in Shiro to do this, a callback of some
>> >> >>> > sort,
>> >> >>> > or
>> >> >>> > some other method? Or should I be doing this in my application?
>> >> >>> > Also, I can't seem to view much of the documentation. All the
>> links
>> >> >>> > on
>> >> >>> > the
>> >> >>> > following page require an Apache login. Is it supposed to be this
>> >> >>> > way?
>> >> >>> > http://incubator.apache.org/shiro/core.html
>> >> >>> > Thanks!
>> >> >>> > Tauren
>> >> >>> >
>> >> >>> >
>> >> >>
>> >> >
>> >> >
>> >
>> >
>>
>
>

Re: Keeping track of user's last login date

Posted by Tauren Mills <ta...@tauren.com>.
Les,

Thanks for the help.  However, now I'm having a problem
with getRememberedPrincipals() being called dozens of times per page
view, causing my "accessed" property to be updated many times, which is
obviously not ideal.

I believe this is because my application is running in Jetty, so every
image, JS, CSS, and other resource is causing a request to be created. My
cookie is set to / since I need it to work for many different paths.

Any suggestions on how to only update my "accessed" property a single time
per session?  I don't need the property updated with every request, just
when they first access the site for a session is fine.  Basically, the
property I currently called "accessed" would actually be more accurately
called "lastLogin".

Below is code if it helps.

Thanks,
Tauren

---

public class MyRememberMeManager extends CookieRememberMeManager {

private MemberService memberService;

    @Autowired
public void setMemberService(MemberService memberService) {
this.memberService = memberService;
}

@Override
public PrincipalCollection getRememberedPrincipals(SubjectContext
subjectContext) {
PrincipalCollection principals =
super.getRememberedPrincipals(subjectContext);
if ( principals != null ) {
Long id = (Long) principals.getPrimaryPrincipal();
memberService.updateAccessed(id);
}
return principals;
}
}

// MemberServiceImpl.java

public void updateAccessed(Long id) {
updateAccessed(findById(id));
}

public void updateAccessed(Member member) {
member.setAccessed(new Date());
memberDao.save(member);
}


// Spring config

    <bean id="securityManager"
class="org.apache.shiro.web.DefaultWebSecurityManager">
      property instead. -->
        <property name="realm" ref="myRealm"/>
        <property name="rememberMeManager" ref="myRememberMeManager"/>
    </bean>

    <bean name="myRememberMeManager"
class="com.project.security.MyRememberMeManager"/>


On Tue, May 11, 2010 at 10:11 AM, Les Hazlewood <lh...@apache.org>wrote:

> Hi Tauren,
>
> Yes, WebRememberMeManager has been deprecated in favor of the new
> CookieRememberMeManager which uses a new Cookie property and not the
> (now deprecated) CookieAttribute concept.  CookieAttribute was complex
> and confusing.  The new Cookie interface and implementation in
> comparison are much easier to understand and configure.  So, if you
> extend CookieRememberMeManager, you should be closely back to where
> you were when you extended WebRememberMeManager.
>
> As for the SubjectContext - it was added within the last two weeks to
> satisfy a technical requirement: the (now new) SubjectContext.resolve*
> method behavior was needed in multiple places across more than one OO
> hierarchy.  So, we either had to copy-n-paste logic (yuck) or
> consolidate it into a component.  The SubjectContext satisfies this
> need and will stay in place instead of the raw Map.
>
> Also note that for 1.0, we'll be removing all Deprecated classes and
> methods.  Since we're wrapping up coding issues today (and possibly
> tomorrow), we'll be deleting them any time now.
>
> I hope that helps!
>
> Les
>
> On Tue, May 11, 2010 at 9:22 AM, Tauren Mills <ta...@tauren.com> wrote:
> > I'm just getting back to this issue now, and have updated to the latest
> > shiro snapshot.
> > When I started working on this, I had extended WebRememberMeManager, but
> it
> > looks like it is now depricated. What is the recommended approach at this
> > time? Should I be directly extending AbstractRememberMeManager?
> > I also wanted to point out that your example in this thread shows passing
> a
> > Map to getRememberedPrincipals, but in my experience I had to pass a
> > SubjectContext.  Before I proceed further, I just want to make sure that
> I'm
> > heading down the proper path that will be supported in the future, and
> not
> > implement something that I'll have to change later.
> > Thanks!
> > Tauren
> >
> >
> >
> >
> >
> >
> > On Mon, Apr 19, 2010 at 12:14 PM, Les Hazlewood <lh...@apache.org>
> > wrote:
> >>
> >> I committed a change to how cryptography works on Friday - that might
> >> have done something with it (we encrypt principals by default).
> >> However, all the test cases still passed and I know that we do have
> >> some test cases around remember me cookies (WebRememberMeManagerTest).
> >>
> >> Please open a Jira issue in the mean time so we don't lose it.  I'll
> >> try to run the sample web app(s) to see if they exhibit the same
> >> behavior.
> >>
> >> Thanks!
> >>
> >> Les
> >>
> >> On Mon, Apr 19, 2010 at 10:57 AM, Tauren Mills <yo...@gmail.com>
> wrote:
> >> > It seems that my remember me function got broken at some point. All of
> >> > my
> >> > requests do not have the cookie they used to. I've tried logging off
> and
> >> > back in again, but still no cookie.  This is
> >> > causing getRememberedPrincipals
> >> > to run with every single request. Obviously not good.
> >> > Any suggestions on how to track down where the remember me problem is
> >> > coming
> >> > from - why I'm not getting cookies? I haven't done much of anything
> with
> >> > Shiro for months now, and it used to work, so not sure what happened.
> >> > Was it
> >> > broken in some recent release that I may be using?
> >> > Thanks,
> >> > Tauren
> >> > On Mon, Apr 19, 2010 at 3:41 AM, Tauren Mills <yo...@gmail.com>
> >> > wrote:
> >> >>
> >> >> Les,
> >> >> Thanks, I'll look into doing this. Are there any examples of using an
> >> >> AuthenticationListener that I could reference?
> >> >>
> >> >> Tauren
> >> >>
> >> >> On Fri, Apr 16, 2010 at 9:10 AM, Les Hazlewood <
> lhazlewood@apache.org>
> >> >> wrote:
> >> >>>
> >> >>> Hi Tauren,
> >> >>>
> >> >>> You could implement an AuthenticationListener - I typically like to
> do
> >> >>> this for these kinds of operations.
> >> >>>
> >> >>> Since Shiro does not count remember me as a true authentication, the
> >> >>> AuthenticationListener will not be triggered for remember me events.
> >> >>> To do that you would also need to implement your own
> >> >>> RememberMeManager.  Typically subclassing the default one and
> updating
> >> >>> the timestamp in the getRememberedPrincipals method would work:
> >> >>>
> >> >>> @Override
> >> >>> public PrincipalCollection getRememberedPrincipals(Map
> subjectContext)
> >> >>> {
> >> >>>    PrincipalCollection principals =
> >> >>> super.getRememberedPrincipals(subjectContext);
> >> >>>    if ( principals != null ) {
> >> >>>        int userId = principals.getPrimaryPrincipal();
> >> >>>        //update the last login timestamp for user with this id here
> >> >>>    }
> >> >>> }
> >> >>>
> >> >>> The above method is called only if the current Subject/session does
> >> >>> not yet have an identity associated with it.
> >> >>>
> >> >>> The AuthenticationListener + the above overridden method should do
> it!
> >> >>>
> >> >>> Cheers,
> >> >>>
> >> >>> Les
> >> >>>
> >> >>> On Thu, Apr 15, 2010 at 8:37 PM, Tauren Mills <ta...@groovee.com>
> >> >>> wrote:
> >> >>> > What would be the best way to update properties of a member on
> >> >>> > successful
> >> >>> > authentication? Basically, there is a Member.lastLogin property
> that
> >> >>> > I
> >> >>> > want
> >> >>> > updated with the current date every time a member comes back to a
> >> >>> > site
> >> >>> > and
> >> >>> > logs in.  However, this should also support rememberme
> >> >>> > authentications. I
> >> >>> > don't necessarily want to update the lastLogin property on every
> >> >>> > single
> >> >>> > interaction the user has on the site, just once for each session.
> >> >>> > Is there some technique in Shiro to do this, a callback of some
> >> >>> > sort,
> >> >>> > or
> >> >>> > some other method? Or should I be doing this in my application?
> >> >>> > Also, I can't seem to view much of the documentation. All the
> links
> >> >>> > on
> >> >>> > the
> >> >>> > following page require an Apache login. Is it supposed to be this
> >> >>> > way?
> >> >>> > http://incubator.apache.org/shiro/core.html
> >> >>> > Thanks!
> >> >>> > Tauren
> >> >>> >
> >> >>> >
> >> >>
> >> >
> >> >
> >
> >
>

Re: Keeping track of user's last login date

Posted by Les Hazlewood <lh...@apache.org>.
Hi Tauren,

Yes, WebRememberMeManager has been deprecated in favor of the new
CookieRememberMeManager which uses a new Cookie property and not the
(now deprecated) CookieAttribute concept.  CookieAttribute was complex
and confusing.  The new Cookie interface and implementation in
comparison are much easier to understand and configure.  So, if you
extend CookieRememberMeManager, you should be closely back to where
you were when you extended WebRememberMeManager.

As for the SubjectContext - it was added within the last two weeks to
satisfy a technical requirement: the (now new) SubjectContext.resolve*
method behavior was needed in multiple places across more than one OO
hierarchy.  So, we either had to copy-n-paste logic (yuck) or
consolidate it into a component.  The SubjectContext satisfies this
need and will stay in place instead of the raw Map.

Also note that for 1.0, we'll be removing all Deprecated classes and
methods.  Since we're wrapping up coding issues today (and possibly
tomorrow), we'll be deleting them any time now.

I hope that helps!

Les

On Tue, May 11, 2010 at 9:22 AM, Tauren Mills <ta...@tauren.com> wrote:
> I'm just getting back to this issue now, and have updated to the latest
> shiro snapshot.
> When I started working on this, I had extended WebRememberMeManager, but it
> looks like it is now depricated. What is the recommended approach at this
> time? Should I be directly extending AbstractRememberMeManager?
> I also wanted to point out that your example in this thread shows passing a
> Map to getRememberedPrincipals, but in my experience I had to pass a
> SubjectContext.  Before I proceed further, I just want to make sure that I'm
> heading down the proper path that will be supported in the future, and not
> implement something that I'll have to change later.
> Thanks!
> Tauren
>
>
>
>
>
>
> On Mon, Apr 19, 2010 at 12:14 PM, Les Hazlewood <lh...@apache.org>
> wrote:
>>
>> I committed a change to how cryptography works on Friday - that might
>> have done something with it (we encrypt principals by default).
>> However, all the test cases still passed and I know that we do have
>> some test cases around remember me cookies (WebRememberMeManagerTest).
>>
>> Please open a Jira issue in the mean time so we don't lose it.  I'll
>> try to run the sample web app(s) to see if they exhibit the same
>> behavior.
>>
>> Thanks!
>>
>> Les
>>
>> On Mon, Apr 19, 2010 at 10:57 AM, Tauren Mills <yo...@gmail.com> wrote:
>> > It seems that my remember me function got broken at some point. All of
>> > my
>> > requests do not have the cookie they used to. I've tried logging off and
>> > back in again, but still no cookie.  This is
>> > causing getRememberedPrincipals
>> > to run with every single request. Obviously not good.
>> > Any suggestions on how to track down where the remember me problem is
>> > coming
>> > from - why I'm not getting cookies? I haven't done much of anything with
>> > Shiro for months now, and it used to work, so not sure what happened.
>> > Was it
>> > broken in some recent release that I may be using?
>> > Thanks,
>> > Tauren
>> > On Mon, Apr 19, 2010 at 3:41 AM, Tauren Mills <yo...@gmail.com>
>> > wrote:
>> >>
>> >> Les,
>> >> Thanks, I'll look into doing this. Are there any examples of using an
>> >> AuthenticationListener that I could reference?
>> >>
>> >> Tauren
>> >>
>> >> On Fri, Apr 16, 2010 at 9:10 AM, Les Hazlewood <lh...@apache.org>
>> >> wrote:
>> >>>
>> >>> Hi Tauren,
>> >>>
>> >>> You could implement an AuthenticationListener - I typically like to do
>> >>> this for these kinds of operations.
>> >>>
>> >>> Since Shiro does not count remember me as a true authentication, the
>> >>> AuthenticationListener will not be triggered for remember me events.
>> >>> To do that you would also need to implement your own
>> >>> RememberMeManager.  Typically subclassing the default one and updating
>> >>> the timestamp in the getRememberedPrincipals method would work:
>> >>>
>> >>> @Override
>> >>> public PrincipalCollection getRememberedPrincipals(Map subjectContext)
>> >>> {
>> >>>    PrincipalCollection principals =
>> >>> super.getRememberedPrincipals(subjectContext);
>> >>>    if ( principals != null ) {
>> >>>        int userId = principals.getPrimaryPrincipal();
>> >>>        //update the last login timestamp for user with this id here
>> >>>    }
>> >>> }
>> >>>
>> >>> The above method is called only if the current Subject/session does
>> >>> not yet have an identity associated with it.
>> >>>
>> >>> The AuthenticationListener + the above overridden method should do it!
>> >>>
>> >>> Cheers,
>> >>>
>> >>> Les
>> >>>
>> >>> On Thu, Apr 15, 2010 at 8:37 PM, Tauren Mills <ta...@groovee.com>
>> >>> wrote:
>> >>> > What would be the best way to update properties of a member on
>> >>> > successful
>> >>> > authentication? Basically, there is a Member.lastLogin property that
>> >>> > I
>> >>> > want
>> >>> > updated with the current date every time a member comes back to a
>> >>> > site
>> >>> > and
>> >>> > logs in.  However, this should also support rememberme
>> >>> > authentications. I
>> >>> > don't necessarily want to update the lastLogin property on every
>> >>> > single
>> >>> > interaction the user has on the site, just once for each session.
>> >>> > Is there some technique in Shiro to do this, a callback of some
>> >>> > sort,
>> >>> > or
>> >>> > some other method? Or should I be doing this in my application?
>> >>> > Also, I can't seem to view much of the documentation. All the links
>> >>> > on
>> >>> > the
>> >>> > following page require an Apache login. Is it supposed to be this
>> >>> > way?
>> >>> > http://incubator.apache.org/shiro/core.html
>> >>> > Thanks!
>> >>> > Tauren
>> >>> >
>> >>> >
>> >>
>> >
>> >
>
>