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 <[email protected]>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 <[email protected]> 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 <[email protected]> > > 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 <[email protected]> > 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 < > [email protected]> > >> > 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 <[email protected]> > >> >> 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 <[email protected]> > >> >> > 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 > >> >> >> <[email protected]> > >> >> >> 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 < > [email protected]> > >> >> >>> 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 > >> >> >>> > > >> >> >>> > > >> >> >> > >> >> > > >> >> > > >> > > >> > > > > > >
