You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@shiro.apache.org by dan <da...@bamlabs.com> on 2011/04/21 02:07:02 UTC

Daemon Task

Hi --

In my web application, I am trying to run a daemon task.  This task is run
in the same JVM but 
from outside the normal web/servlet processing.

I am attempting to create a subject and bind it to this task like this:

    Subject subject = new Subject.Builder().buildSubject();

    ThreadState state = new SubjectThreadState(subject);
    state.bind();
    try {
        // run tasks
    } finally {
        state.clear();
    }

but it throws this:

org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager
accessible to the calling code, either bound to the
org.apache.shiro.util.ThreadContext or as a vm static singleton.  This is an
invalid application configuration.
    at
org.apache.shiro.SecurityUtils.getSecurityManager(SecurityUtils.java:123)

when it is building the subject.

I believe I would like Shiro to use the exact, same SecurityManager that all
the standard processing uses, which is DefaultWebSecurityManager, but I
don't understand how to initialize this "thread" to use it.  I have read
through the documentation and have I tried variations of
SecurityUtils.setSecurityManger() with no luck.

Thanks much,
Dan 

--
View this message in context: http://shiro-user.582556.n2.nabble.com/Daemon-Task-tp6292830p6292830.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Daemon Task

Posted by dan <da...@bamlabs.com>.
Les,

Actually, extending IniShiroFilter worked perfectly fine in my app. 
Background tasks can be considered "out of band" processes and thus it seems
reasonable to pull in a saved securityManager instance to get them rolling. 
I can see that the enhancement you are considering for 1.2 will allow for
even less customization code in the app, which is nice.

Thanks very much for your quick and accurate assessment of my issue,

Dan

--
View this message in context: http://shiro-user.582556.n2.nabble.com/Daemon-Task-tp6292830p6307703.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Daemon Task

Posted by Les Hazlewood <lh...@apache.org>.
On Wed, Apr 20, 2011 at 6:07 PM, dan <da...@bamlabs.com> wrote:
> Hi Les,
>
> Yes, in my first post I didn't want to overwhelm you with irrelevant details
> so it was a bit short... ;)
>
> Our app currently uses Shiro in the standard web servlet way, that is, I
> have IniShiroFilter in my web.xml file and all incoming http requests are
> intercepted by Shiro.  In my shiro.ini, I don't specify a securityManager
> class, so it decides to instantiate a DefaultWebSecurityManager on its own,
> which is fine.
>
> For our deamon processes, we have a web filter and within its init() method,
> we instantiate some objects, including a singleton, initialize our scheduler
> and then process to kick off Java threads here and there.  In my deamon
> task, when I call getSecurityManager(), it can't find any threadlocal
> information (which I expect). Then it tries the static secuirtyManager which
> also returns null so the exception is thrown.

Ah, I see now.

At the moment, it is expected that work on other threads is 'kicked
off' from a request-initiated thread.  That is, during a web request,
when there is a Subject available, you can call subject.associateWith*
and take the resulting object and toss it off to an ExecutorService
(or better yet, use Shiro's SubjectAwareExecutorService
implementations so you don't have to use the subject directly).

But, assuming you don't want to do this (or can't do this), there is
an easy, albeit not ideal, solution:

Subclass the IniShiroFilter and override the init() method:

public void init() {
    super.init();
    SecurityUtils.setSecurityManager(getSecurityManager());
}

and specify that class in web.xml

That will ensure that all uses of SecurityUtils.getSecurityManager()
will fall back to static memory if one is not available on the current
thread.

To solve this in a better way, I just created
https://issues.apache.org/jira/browse/SHIRO-287

It will be easy enough to implement this shortly such that it will be in 1.2.

HTH!

Les

Re: Daemon Task

Posted by dan <da...@bamlabs.com>.
Hi Les,

Yes, in my first post I didn't want to overwhelm you with irrelevant details
so it was a bit short... ;)

Our app currently uses Shiro in the standard web servlet way, that is, I
have IniShiroFilter in my web.xml file and all incoming http requests are
intercepted by Shiro.  In my shiro.ini, I don't specify a securityManager
class, so it decides to instantiate a DefaultWebSecurityManager on its own,
which is fine.

For our deamon processes, we have a web filter and within its init() method,
we instantiate some objects, including a singleton, initialize our scheduler
and then process to kick off Java threads here and there.  In my deamon
task, when I call getSecurityManager(), it can't find any threadlocal
information (which I expect). Then it tries the static secuirtyManager which
also returns null so the exception is thrown.

(We don't do anything special with classloading.)

If I could "discover" a reference to the DefaultWebSecurityManger instance,
I could then call setSecurityManager() and that I believe would work.  OR...
if my deamon thread could "register" itself with threadlocal info, then that
might work also.  In either case, perhaps you can comment on how you would
recommend this should be approached.

BTW, I don't think it's possible, but it would be cool if I could construct
a Subject with certain roles, such as: new
Subject.Builder().withRole("deamon").buildSubject().

Thanks a lot,
Dan


--
View this message in context: http://shiro-user.582556.n2.nabble.com/Daemon-Task-tp6292830p6292929.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Daemon Task

Posted by Les Hazlewood <lh...@apache.org>.
Hi Dan,

What is your environment like?  How do you initialize the
SecurityManager - via the normal Shiro Filter mechanism?  I'm trying
to discover how you might acquire the SecurityManager instance.

Also, I'm not sure what you mean 'tried variations of
SecurityUtils.setSecurityManager(securityManager)'.  If you call that
method, the SecurityManager instance passed in will be globally
accessible in static memory and always available to the
Subject.Builder instances.  The only way this wouldn't work is if you
have different class loaders and each ClassLoader has its own
SecurityUtils class instance.  This would be very odd however.

You can verify this by looking at the code here:

http://svn.apache.org/repos/asf/shiro/trunk/core/src/main/java/org/apache/shiro/SecurityUtils.java

The getSecurityManager() method will try a ThreadLocal first, and if
not there, try the static member variable.  If you get an exception
from getSecurityManager(), it is definitely not being set in static
memory (e.g. there is a classloader issue involved or when you called
setSecurityManager, it was a null reference).

Finally, once you have constructed your subject via the
Subject.Builder, I'd recommend using the subject.execute* methods
instead of messing with ThreadState mechanisms (unless you're doing
more 'frameworky' kind of stuff that you've left out for brevity).

Anyway, if you can help answer the configuration questions, I'm sure
we'll get it working.

Cheers,

Les

On Wed, Apr 20, 2011 at 5:07 PM, dan <da...@bamlabs.com> wrote:
> Hi --
>
> In my web application, I am trying to run a daemon task.  This task is run
> in the same JVM but
> from outside the normal web/servlet processing.
>
> I am attempting to create a subject and bind it to this task like this:
>
>    Subject subject = new Subject.Builder().buildSubject();
>
>    ThreadState state = new SubjectThreadState(subject);
>    state.bind();
>    try {
>        // run tasks
>    } finally {
>        state.clear();
>    }
>
> but it throws this:
>
> org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager
> accessible to the calling code, either bound to the
> org.apache.shiro.util.ThreadContext or as a vm static singleton.  This is an
> invalid application configuration.
>    at
> org.apache.shiro.SecurityUtils.getSecurityManager(SecurityUtils.java:123)
>
> when it is building the subject.
>
> I believe I would like Shiro to use the exact, same SecurityManager that all
> the standard processing uses, which is DefaultWebSecurityManager, but I
> don't understand how to initialize this "thread" to use it.  I have read
> through the documentation and have I tried variations of
> SecurityUtils.setSecurityManger() with no luck.
>
> Thanks much,
> Dan
>
> --
> View this message in context: http://shiro-user.582556.n2.nabble.com/Daemon-Task-tp6292830p6292830.html
> Sent from the Shiro User mailing list archive at Nabble.com.