You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@shiro.apache.org by Cemo <ce...@gmail.com> on 2012/11/15 23:21:43 UTC

How SecurityUtil works

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.

My questions:

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.

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.

Could someone please shed light on these questions?

Thanks

Re: How SecurityUtil works

Posted by Cemo <ce...@gmail.com>.
A fantastically thorough explanation.
Thank you.

On 16 November 2012 20:02, Les Hazlewood <lh...@apache.org> 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
>

Re: How SecurityUtil works

Posted by Les Hazlewood <lh...@apache.org>.
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