> def sessionValidationScheduler = new > org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler() > sessionValidationScheduler.setInterval(30000) > shiroSecurityManager.sessionManager.sessionValidationScheduler = > sessionValidationScheduler > > One thing worthy of note is that unless I have the last 3 lines, where I > explicitly configure a sessionValidationScheduler, nothing is written to > the log, presumably meaning that there is no default validation > scheduler. I don't know whether this is expected, or whether it's a > quirk of the plugin.
Ah, I see what is happening. I think this is a bug - or at least confusing at best. Let me explain: When a SessionValidationScheduler instance is created outside of Shiro's internal mechanisms and explicitly set on the sessionManager (an AbstractValidatingSessionManager instance), the sessionManager will only ensure that scheduler.enableSessionValidation(); is invoked. It does _not_ ensure that the scheduler is configured or even that it references the sessionManager. It is assumed that whoever created the Scheduler instance did this explicitly. So in the code snippet above, the ExecutorServiceSessionValidationScheduler instance is created, but it is not given a reference to the SessionManager. A scheduler's primary purpose is to periodically invoke the ValidatingSessionManager.validateSessions() method. Without a reference to the sessionManager, it cannot function. So in the above code, while the scheduler is created, and it might start running, it never actually validates any sessions. I agree this is not very 'Shiroy' - you would assume that when setting a scheduler, the sessionManager should probably automatically make itself the scheduler's target. So, there are two solutions for this immediate problem: 1. Don't configure the Scheduler explicitly and let Shiro create it. You can set the validation interval as a property on the sessionManager instance and it will be relayed to the implicitly created Scheduler. For example: securityManager.sessionManager.sessionValidationInterval = timeInMillis 2. Create any Scheduler instance you wish, but ensure it has a reference to the sessionManager: sessionValidationScheduler = org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler sessionValidationScheduler.interval = timeInMillis sessionValidationScheduler.sessionManager = $sessionManager securityManager.sessionManager.sessionValidationScheduler = $sessionValidationScheduler Either should do it. Now that that's covered, I think I should make some points about validation scheduling in a clustered environment: *Clustering* In a clustered environment where you might have N number of application nodes, all of which are Shiro enabled - and all of which point to the same session store - you only really need one of those app instances at any point in time to perform session validation. It just doesn't make sense to run a scheduler on all nodes if only one node needs to be doing the work. Running the validation only one node also means the other nodes are freed up for other things (like processing requests). As such, you ideally would not want to use the ExecutorServiceSessionValidationScheduler since it is not 'cluster aware'. One option is to have only one node have a slightly different Shiro config so it only did the session validation, but this is brittle IMO - you have to maintain separate configs, and if that node died, another wouldn't automatically take its place, etc. So there are two options for session validation in clusters that I think works quite well: 1. Turn off Shiro's session validation mechanism entirely and rely on your clustered cache to evict entries. The cache entry TTL is effectively the session timeout. I believe you're already going down this route, and I think it is a sound option. Assuming you don't need to retain stopped/expired sessions for reporting purposes, this is also the easiest approach (on the Shiro side at least) because it reduces your Shiro config. 2. Use a cluster-compatible SessionValidationScheduler implementation. The Shiro quartz module exists explicitly because of this need: Quartz has the ability to obtain a cluster-wide lock (e.g. using an RDBMS table for example) to ensure that one node and only one node at a time runs the Quartz Job. This ensures that other nodes are free to process requests instead of all nodes attempting to validate active sessions at around the same time (which would be extremely inefficient and potentially cause performance problems in a cluster). Well, I hope that helps clear things up! Let us know how it goes... Best, -- Les Hazlewood CTO, Katasoft | http://www.katasoft.com | 888.391.5282 twitter: @lhazlewood | http://twitter.com/lhazlewood katasoft blog: http://www.katasoft.com/blogs/lhazlewood personal blog: http://leshazlewood.com
