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 <[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 >>> >> >>> > >>> >> >>> > >>> >> >> >>> >> > >>> >> > >>> > >>> > >> >> >
