shiro-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Les Hazlewood <lhazlew...@apache.org>
Subject Re: How SecurityUtil works
Date Fri, 16 Nov 2012 18:02:07 GMT
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

Mime
View raw message