You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@shiro.apache.org by Rui Vilão <rp...@gmail.com> on 2011/08/02 18:28:46 UTC

Reusing security manager

Hi all,

I have an application server with several services. One of these services, I
call it security-service, is responsible for configuring the shiro realm and
instantiates a SecurityManager (for now lets assume it's a web security
manager). This service enables getting the realm instance as well as the
SecurityManager instance previously created.

The server also enables web content (through jetty).

Now, what do I want to do:

I want to be able to authenticate users and share sessions across different
web applications.
I also want to use the filters you provide in shiro-web.

A good approach would be using the IniShiroFilter but in a way that I could
specify my previously created SecurityManager.

Is it possible to use filters with an instance of SecurityManager already
created without heavy modifications?

I'm really lost here, I could use a hand.
Thanks in advance,

Rui

Re: Reusing security manager

Posted by Les Hazlewood <lh...@apache.org>.
On Tue, Aug 2, 2011 at 3:08 PM, Rui Vilão <rp...@gmail.com> wrote:
>> and both apps
>> point to the same session data store, then yes :)
>
> Now here... I will have to turn Ehcache on right? Something like you say in
> http://shiro.apache.org/session-management.html although in my case I think
> it will be programmatically.

Yes, this is one option that works ok on apps running on the same
physical host.  If you have apps across hosts, you'll need to enable a
clustered cache (like adding TerraCotta to support Ehcache) so the
same session data is accessible across multiple hosts (this might be
smart even with apps on a single host to provide an additional level
of guarantee for cache coherency).

Or you can create a SessionDAO to use whatever shared data store you
like (e.g. RDBMS or NoSQL data store like Cassandra or Mongo).  Just
configure the same SessionDAO in each Shiro-enabled app, and it should
be fine.

Cheers,

-- 
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

Re: Reusing security manager

Posted by Rui Vilão <rp...@gmail.com>.
My comments inline.

--
Rui

On Tue, Aug 2, 2011 at 10:36 PM, Les Hazlewood <lh...@apache.org>wrote:

> If you allow sessions to be used


This is done implicitly and by default right?


> , and both apps can access the same
> JSESSIONID (either via a shared cookie or request param)


This too I believe.


> and both apps
> point to the same session data store, then yes :)
>

Now here... I will have to turn Ehcache on right? Something like you say in
http://shiro.apache.org/session-management.html although in my case I think
it will be programmatically.


>
> On Tue, Aug 2, 2011 at 2:09 PM, Rui Vilão <rp...@gmail.com> wrote:
> > So you're saying that, for example I use the authc filter in one webapp
> > (performing thelogin) and then use the UserFilter in another webapp with
> the
> > same browser, same session I will be authenticated in the second webapp?
> > --
> > Rui
> >
> > On Tue, Aug 2, 2011 at 9:54 PM, Les Hazlewood <lh...@apache.org>
> wrote:
> >>
> >> I'm not sure why you're using the Subject.Builder.
> >>
> >> If you subclass the IniShiroFilter (or its parent
> >> AbstractShiroFilter), the WebSubject is already created and bound to
> >> the thread for you so that SecurityUtils.getSubject() will work
> >> correctly (and return WebSubject) instances.
> >>
> >> The AbstractShiroFilter will also build the WebSubject according to
> >> the JSESSIONID as expected - no need to re-implement this yourself.
> >>
> >>
> >>
> http://svn.apache.org/repos/asf/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/AbstractShiroFilter.java
> >>
> >> HTH,
> >>
> >> Les
>

Re: Reusing security manager

Posted by Les Hazlewood <lh...@apache.org>.
If you allow sessions to be used, and both apps can access the same
JSESSIONID (either via a shared cookie or request param) and both apps
point to the same session data store, then yes :)

On Tue, Aug 2, 2011 at 2:09 PM, Rui Vilão <rp...@gmail.com> wrote:
> So you're saying that, for example I use the authc filter in one webapp
> (performing thelogin) and then use the UserFilter in another webapp with the
> same browser, same session I will be authenticated in the second webapp?
> --
> Rui
>
> On Tue, Aug 2, 2011 at 9:54 PM, Les Hazlewood <lh...@apache.org> wrote:
>>
>> I'm not sure why you're using the Subject.Builder.
>>
>> If you subclass the IniShiroFilter (or its parent
>> AbstractShiroFilter), the WebSubject is already created and bound to
>> the thread for you so that SecurityUtils.getSubject() will work
>> correctly (and return WebSubject) instances.
>>
>> The AbstractShiroFilter will also build the WebSubject according to
>> the JSESSIONID as expected - no need to re-implement this yourself.
>>
>>
>> http://svn.apache.org/repos/asf/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/AbstractShiroFilter.java
>>
>> HTH,
>>
>> Les

Re: Reusing security manager

Posted by Rui Vilão <rp...@gmail.com>.
So you're saying that, for example I use the authc filter in one webapp
(performing thelogin) and then use the UserFilter in another webapp with the
same browser, same session I will be authenticated in the second webapp?

--
Rui

On Tue, Aug 2, 2011 at 9:54 PM, Les Hazlewood <lh...@apache.org> wrote:

> I'm not sure why you're using the Subject.Builder.
>
> If you subclass the IniShiroFilter (or its parent
> AbstractShiroFilter), the WebSubject is already created and bound to
> the thread for you so that SecurityUtils.getSubject() will work
> correctly (and return WebSubject) instances.
>
> The AbstractShiroFilter will also build the WebSubject according to
> the JSESSIONID as expected - no need to re-implement this yourself.
>
>
> http://svn.apache.org/repos/asf/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/AbstractShiroFilter.java
>
> HTH,
>
> Les
>

Re: Reusing security manager

Posted by Les Hazlewood <lh...@apache.org>.
I'm not sure why you're using the Subject.Builder.

If you subclass the IniShiroFilter (or its parent
AbstractShiroFilter), the WebSubject is already created and bound to
the thread for you so that SecurityUtils.getSubject() will work
correctly (and return WebSubject) instances.

The AbstractShiroFilter will also build the WebSubject according to
the JSESSIONID as expected - no need to re-implement this yourself.

http://svn.apache.org/repos/asf/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/AbstractShiroFilter.java

HTH,

Les

Re: Reusing security manager

Posted by Rui Vilão <rp...@gmail.com>.
Hi,

Thanks again for replying.

What I've done is below (this is just to test):

I subclassed WebIniSecurityManagerFactory like this.

    public static class WebIniSecurityManagerFactoryMine extends
WebIniSecurityManagerFactory {

        public WebIniSecurityManagerFactoryMine() {
            super();
        }

        public WebIniSecurityManagerFactoryMine(Ini init) {
            super(init);
        }

        @Override
        protected SecurityManager createDefaultInstance() {
            final SecurityManager securityManager =
PulseBindings.<PulseSecurity>security().getSecurityManager();
            return securityManager;
        }

        @Override
        protected SecurityManager createInstance(Ini ini) {
            super.createInstance(ini);
            final SecurityManager securityManager =
PulseBindings.<PulseSecurity>security().getSecurityManager();
            return securityManager;
        }

    }

Then I subclassed IniShiroFilter like this:

    @Override
    protected Map<String, ?> applySecurityManager(Ini ini) {
        WebIniSecurityManagerFactory factory;
        if (CollectionUtils.isEmpty(ini)) {
            factory = new WebIniSecurityManagerFactoryMine();
        } else {
            factory = new WebIniSecurityManagerFactoryMine(ini);
        }

        // Create the security manager and check that it implements
WebSecurityManager.
        // Otherwise, it can't be used with the filter.
        SecurityManager securityManager = factory.getInstance();
        if (!(securityManager instanceof WebSecurityManager)) {
            String msg = "The configured security manager is not an instance
of WebSecurityManager, so " +
                    "it can not be used with the Shiro servlet filter.";
            throw new ConfigurationException(msg);
        }

        setSecurityManager((WebSecurityManager) securityManager);

        return factory.getBeans();
    }

So it can use my factory that not creates an instance but uses the already
running one.

Then I subclassed UserFilter like:

    @Override
    protected Subject getSubject(ServletRequest request, ServletResponse
response) {
        Subject sub;
        final String jsessionId = request.getParameter(JSESSIONID_KEY);
        if (jsessionId != null) {
            sub = new
Subject.Builder().sessionId(jsessionId).buildSubject();
        } else {
            sub = super.getSubject(request, response);
        }

        request.setAttribute("subject", sub);

        return sub;
    }

So the idea is, if JSESSIONID is sent in the parameters it is possible that
a session is already in use and I try to get the subject using the session,
if not I use your implementation.

I really don't know why (and I'm sure only one SessionManager is in use as
well as SecurityManager because I ran the application with a profiler and
only on instance of each is in use) but I'm getting this error when I try to
use Subject.Builder().sessionId(...):

java.lang.IllegalArgumentException: SessionKey must be an HTTP compatible
implementation.
                         at
org.apache.shiro.web.session.mgt.ServletContainerSessionManager.getSession(ServletContainerSessionManager.java:70)
                         at
org.apache.shiro.mgt.SessionsSecurityManager.getSession(SessionsSecurityManager.java:125)
                         at
org.apache.shiro.mgt.DefaultSecurityManager.resolveContextSession(DefaultSecurityManager.java:394)
                         at
org.apache.shiro.mgt.DefaultSecurityManager.resolveSession(DefaultSecurityManager.java:380)
                         at
org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:329)
                         at
org.apache.shiro.subject.Subject$Builder.buildSubject(Subject.java:829)
                         at
filter.DistributedSessionFilter.getSubject(DistributedSessionFilter.java:37)
                         at
org.apache.shiro.web.filter.authc.UserFilter.isAccessAllowed(UserFilter.java:53)
                         at
org.apache.shiro.web.filter.AccessControlFilter.onPreHandle(AccessControlFilter.java:162)
                         at
org.apache.shiro.web.filter.PathMatchingFilter.preHandle(PathMatchingFilter.java:177)
                         at
org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:131)
                         at
org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:81)
                         at
org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
                         at
org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:359)
                         at
org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:275)
                         at
org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
                         at
org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
                         at
org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:344)
                         at
org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:272)
                         at
org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:81)
                         at
org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1187)
                         at
org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:421)
                         at
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:119)
                         at
org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:456)
                         at
org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
                         at
org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:924)
                         at
org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:358)
                         at
org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:183)
                         at
org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:860)
                         at
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
                         at
org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:245)
                         at
org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126)
                         at
org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:113)
                         at
org.eclipse.jetty.server.Server.handle(Server.java:335)
                         at
org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:588)
                         at
org.eclipse.jetty.server.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:1029)
                         at
org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:549)
                         at
org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:211)
                         at
org.eclipse.jetty.server.HttpConnection.handle(HttpConnection.java:418)
                         at
org.eclipse.jetty.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:489)
                         at
org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:436)
                         at java.lang.Thread.run(Thread.java:662)

Do you have any clue why this is happening?

Thanks in advance,
--
Rui


On Tue, Aug 2, 2011 at 8:18 PM, Les Hazlewood <lh...@apache.org> wrote:

> Also note that the [urls] INI section is really there to configure
> filter chains on a Shiro FilterChainManager instance.  You could
> configure your own FilterChainManager (and create filter chains as
> necessary) yourself by invoking methods on it directly (see the
> DefaultFilterChainManager class).
>
> So, in summary:
>
> The [main] section configures the SecurityManager and its object
> graph, including realms.
>
> The [urls] section configures filter chains which are set on a
> FilterChainManager.  At runtime, a FilterChainResolver asks the
> FilterChainManager for a filter chain to execute for the corresponding
> request/response.  If the FilterChainManager returns one, that is
> executed.  If it doesn't, the original chain provided by the servlet
> container is executed.
>
> If you didn't want to use INI, you could subclass the
> AbstractShiroFilter and provide your own means (code, DI, whatever) of
> providing the SecurityManager and FilterChainResolver instances.
>
> HTH,
>
> Les
>
> On Tue, Aug 2, 2011 at 12:03 PM, Les Hazlewood <lh...@apache.org>
> wrote:
> > The SecurityManager is an object graph with nested components (some of
> > which are Realms).  You can instantiate a SecurityManager and call
> > setter methods on it or any of its internal components just fine.
> >
> > The INI [main] section is just a text-based way of configuring the
> > Security manager object graph.  I often call it 'poor man's Dependency
> > Injection' since it works like Spring or Guice, just not quite as
> > powerful.  You don't have to use it however - you can call the methods
> > you want via standard Java code or reflection if you like (or use
> > something like Spring or Guice which does this for you).
> >
> > Cheers,
> >
> > Les
>

Re: Reusing security manager

Posted by Les Hazlewood <lh...@apache.org>.
Also note that the [urls] INI section is really there to configure
filter chains on a Shiro FilterChainManager instance.  You could
configure your own FilterChainManager (and create filter chains as
necessary) yourself by invoking methods on it directly (see the
DefaultFilterChainManager class).

So, in summary:

The [main] section configures the SecurityManager and its object
graph, including realms.

The [urls] section configures filter chains which are set on a
FilterChainManager.  At runtime, a FilterChainResolver asks the
FilterChainManager for a filter chain to execute for the corresponding
request/response.  If the FilterChainManager returns one, that is
executed.  If it doesn't, the original chain provided by the servlet
container is executed.

If you didn't want to use INI, you could subclass the
AbstractShiroFilter and provide your own means (code, DI, whatever) of
providing the SecurityManager and FilterChainResolver instances.

HTH,

Les

On Tue, Aug 2, 2011 at 12:03 PM, Les Hazlewood <lh...@apache.org> wrote:
> The SecurityManager is an object graph with nested components (some of
> which are Realms).  You can instantiate a SecurityManager and call
> setter methods on it or any of its internal components just fine.
>
> The INI [main] section is just a text-based way of configuring the
> Security manager object graph.  I often call it 'poor man's Dependency
> Injection' since it works like Spring or Guice, just not quite as
> powerful.  You don't have to use it however - you can call the methods
> you want via standard Java code or reflection if you like (or use
> something like Spring or Guice which does this for you).
>
> Cheers,
>
> Les

Re: Reusing security manager

Posted by Les Hazlewood <lh...@apache.org>.
The SecurityManager is an object graph with nested components (some of
which are Realms).  You can instantiate a SecurityManager and call
setter methods on it or any of its internal components just fine.

The INI [main] section is just a text-based way of configuring the
Security manager object graph.  I often call it 'poor man's Dependency
Injection' since it works like Spring or Guice, just not quite as
powerful.  You don't have to use it however - you can call the methods
you want via standard Java code or reflection if you like (or use
something like Spring or Guice which does this for you).

Cheers,

Les

Re: Reusing security manager

Posted by Rui Vilão <rp...@gmail.com>.
Hi,

Thanks for the reply.

I need to instantiate the realms I extended and I believe I can't do this,
for example using a shiro.ini file (I need to pass several arguments among
other calls). How can I instantiate a new shiro environment on a web project
without a shiro.ini file?

--
Rui

On Tue, Aug 2, 2011 at 6:59 PM, Les Hazlewood <lh...@apache.org> wrote:

> Hi Rui,
>
> If your only goal is to share sessions across applications, the
> easiest thing to do is configure a SessionDAO that 'points' to a
> session data store that is shared by your applications.
>
> This way, each application has its own Shiro environment
> (SecurityManager, filters, etc), which is usually easiest to manage.
> If you use a shared and/or distributed cache (e.g. Ehcache), then each
> application can access the same session store.
>
> Does this help?
>
> Regards,
>
> --
> 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
>

Re: Reusing security manager

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

If your only goal is to share sessions across applications, the
easiest thing to do is configure a SessionDAO that 'points' to a
session data store that is shared by your applications.

This way, each application has its own Shiro environment
(SecurityManager, filters, etc), which is usually easiest to manage.
If you use a shared and/or distributed cache (e.g. Ehcache), then each
application can access the same session store.

Does this help?

Regards,

-- 
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