A fantastically thorough explanation. Thank you. On 16 November 2012 20:02, Les Hazlewood <[email protected]> wrote:
> Hi Cemo, > > Hi, >> >> This is actually a common question rather than Shiro specific. What I >> would like to learn is how org.apache.shiro.SecurityUtils#getSubject is >> working. I have checked necessary parts of the SecurityUtils and >> ThreadContext and I am totally puzzled now. The basic way that I understand >> Shiro's SecurityUtils.getSubject() to work is that it returns the subject >> which is bound to the currently executing thread. Actually I was expecting >> something analogous to RequestLocal instead of ThreadLocal. >> > > This is correct - ThreadContext is a utility helper that wraps a > ThreadLocal Map. > > SecurityUtils.getSubject() assumes that the currently executing thread has > one and only one bound subject. For web apps, this implies there must be a > 1:1 correspondance of a Request and a Thread. But > SecurityUtils.getSubject() is mainly a convenience - Shiro can - and does- > work quite well in any environment. If there isn't a thread-per-request > model, the Shiro end-user (or framework developer) just has to do some > extra work to allow an app developer to use something other than > SecurityUtils. > > Anyway, in a web app today, the Shiro filter will: > > 1. Build the Subject associated with the incoming request (using the > WebSubject.Builder) > 2. Bind that newly created Subject instance to the thread. Subject > instances in memory are lightweight and can be created/destroyed at will. > The subject state itself can (and usually does) live around longer than > that in a session or in Authc/Authz cache. > 3. Execute the filter chain. > 4. Unbind the Subject instance from the thread. > > Again, this assumes one thread per request, but Shiro will work with other > models as long as there is support to access a Subject _somewhere_. > > >> 1. How Shiro ensures a random point of the application has the same >> thread as the subject creater thread to provide same Subject? (Maybe it is >> related to Servlet spec. Would be great pointing necessary part) >> Particularly I am interested in JAX-RS. >> > > I haven't looked in detail to the Servlet 3 spec, but all previous specs > (<= 2.5) indicated a thread-per-request model. When the request was done, > the request thread goes back into the servlet container's thread pool to > service a future request. > > The above steps (1 - 4) use this model to create a subject and then > guarantee the thread is cleaned (step 4) before the thread is returned to > the pool. > > However, for asynchronous flows (maybe the request thread triggers work > that will be executed on another thread), Shiro has support for this too, > via the following mechanisms: > > SubjectAwareExecutor > SubjectAwareExecutorService > SubjectAwareScheduledExecutorService > > These 3 classes implement the respective Java executor* interfaces and > function as follows: > > They all delegate to a 'real' Executor/Service. But when a job (runnable > or callable) is submitted, the implementations will first wrap the > submitted runnable or callable with a custom Shiro runnable or callable. > The Shiro wrapper ensures that, when the job is executed on a different > thread, that the subject is bound (and later cleaned) from the thread that > runs asynchronously. > > This allows you to transparently retain identity of the Shiro subject > across all threads. > > Consider the following code: > > //assume subject 'jsmith' is bound to the current thread > > Callable work = //create callable > > anExecutorService.submit(work); > > When 'work' is run on a different thread, it will execute as the 'jsmith' > subject, and when the execution is finished, the subject will be > cleared/unbound from that thread. And because your code uses a plain > ExecutorService instance, it has no knowledge that Shiro even exists (no > Shiro api imports necessary). > > >> 2. This is the most confusing part of whole subject. How Shiro works at >> servlet 3 container where multiple requests are bounding to single thread. >> > > Shiro's out of the box web support will not function with this model. It > probably definitely could since Shiro is very generic in its architecture - > it would probably just require some glue code to ensure things worked as > expected. > > It might also introduce a required API for webapp developers, e.g. > WebUtils.getSubject(aRequest); instead of using SecurityUtils.getSubject(); > but I haven't looked into the multi-request-per-thread model of the Servlet > 3 spec and don't yet know what would be involved. > > HTH! > > Best, > > -- > Les Hazlewood | @lhazlewood > CTO, Stormpath | http://stormpath.com | @goStormpath | 888.391.5282 > Stormpath wins GigaOM Structure Launchpad Award! http://bit.ly/MvZkMk >
