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/09/16 02:38:22 UTC

Using native web sessions

Hi --

I'm trying to convert our existing shiro-based web project over to native
sessions.  This way, I can handle sessions in a clustered server
environment.

To shiro.ini, I added EnterpriseCacheSessionDAO and set its sessionDAO to a
CacheManager that I have that uses Hazelcast.  I also specified
DefaultWebSessionManager.

In web.xml, BamIniShiroFilter is the first filter.

Now, when I go to page with rememberMe, I see a JSESSIONID with the shiro
format.  Then when I go to another page, it switches to the tomcat format.

When I go to the logon page, it displays JSESSIONID in tomcat's format.

Our application is a bit complex, with a bunch of home-grown stuff and Java
Server Faces.  

I don't understand why any sessions are created with tomcat!  Can you point
me to how to debug this?

Dan


--
View this message in context: http://shiro-user.582556.n2.nabble.com/Using-native-web-sessions-tp6799265p6799265.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Using native web sessions

Posted by dan <da...@bamlabs.com>.
Cool. Thanks!  That was the ticket -- by disabling session-creation in the
jsp page, I was able to get past that issue.  Actually, disabling it is not
a bad thing to do anyway since less resources are consumed.

Thanks again,
Dan

--
View this message in context: http://shiro-user.582556.n2.nabble.com/Using-native-web-sessions-tp6799265p6825070.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Using native web sessions

Posted by Les Hazlewood <lh...@apache.org>.
Oops - my apologies - you have set up a debugger.

Apparently the 'pageNotFound.jsp' page is coded to acquire a session.
Try to ensure that page does not participate in a session, using the
appropriate JSP header, e.g. <%@ session=false ...  (or whatever it is
- I can't remember off the top of my head).

On Fri, Sep 23, 2011 at 8:16 AM, Les Hazlewood <lh...@apache.org> wrote:
> Hi Dan,
>
> I haven't had a chance to look at the JSP stack trace yet, but loading
> a servlet does not start a session.  A developer somewhere - either in
> your codebase or a library you're using - must call
> httpServletRequest.getSession() (or getSession(true)) to start a
> session.
>
> Also, JSP pages by design won't bypass a filter if the filter is
> configured to filter requests that will go to that JSP.  That is, the
> filters always 'sit in front of' JSP pages or Servlets.
>
> If you put a debugger breakpoint on HttpServletRequest.getSession()
> and HttpServletRequest.getSession(true) you will find the culprit in
> no time.  I recommend doing that as it is far more efficient than
> looking at stack traces.
>
> HTH,
>
> --
> 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
>
> On Thu, Sep 22, 2011 at 5:31 PM, dan <da...@bamlabs.com> wrote:
>> Here's another clue about JspServlet.  Looking through the tomcat sources,
>> which includes Jasper, I found that they load JspServlet before anything
>> else.  Here's from their org.apache.catalina.core.StandardWrapper class:
>>
>>    /**
>>     * Return the load-on-startup order value (negative value means
>>     * load on first call).
>>     */
>>    public int getLoadOnStartup() {
>>
>>        if (isJspServlet && loadOnStartup < 0) {
>>            /*
>>             * JspServlet must always be preloaded, because its instance is
>>             * used during registerJMX (when registering the JSP
>>             * monitoring mbean)
>>             */
>>             return Integer.MAX_VALUE;
>>        } else {
>>            return (this.loadOnStartup);
>>        }
>>    }
>>
>> I didn't see anything about this in the list. Perhaps I'm running across
>> this because I'm the first one trying it with native sessions?
>>
>> Dan
>>
>>
>> --
>> View this message in context: http://shiro-user.582556.n2.nabble.com/Using-native-web-sessions-tp6799265p6822446.html
>> Sent from the Shiro User mailing list archive at Nabble.com.
>



-- 
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: Using native web sessions

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

I haven't had a chance to look at the JSP stack trace yet, but loading
a servlet does not start a session.  A developer somewhere - either in
your codebase or a library you're using - must call
httpServletRequest.getSession() (or getSession(true)) to start a
session.

Also, JSP pages by design won't bypass a filter if the filter is
configured to filter requests that will go to that JSP.  That is, the
filters always 'sit in front of' JSP pages or Servlets.

If you put a debugger breakpoint on HttpServletRequest.getSession()
and HttpServletRequest.getSession(true) you will find the culprit in
no time.  I recommend doing that as it is far more efficient than
looking at stack traces.

HTH,

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

On Thu, Sep 22, 2011 at 5:31 PM, dan <da...@bamlabs.com> wrote:
> Here's another clue about JspServlet.  Looking through the tomcat sources,
> which includes Jasper, I found that they load JspServlet before anything
> else.  Here's from their org.apache.catalina.core.StandardWrapper class:
>
>    /**
>     * Return the load-on-startup order value (negative value means
>     * load on first call).
>     */
>    public int getLoadOnStartup() {
>
>        if (isJspServlet && loadOnStartup < 0) {
>            /*
>             * JspServlet must always be preloaded, because its instance is
>             * used during registerJMX (when registering the JSP
>             * monitoring mbean)
>             */
>             return Integer.MAX_VALUE;
>        } else {
>            return (this.loadOnStartup);
>        }
>    }
>
> I didn't see anything about this in the list. Perhaps I'm running across
> this because I'm the first one trying it with native sessions?
>
> Dan
>
>
> --
> View this message in context: http://shiro-user.582556.n2.nabble.com/Using-native-web-sessions-tp6799265p6822446.html
> Sent from the Shiro User mailing list archive at Nabble.com.

Re: Using native web sessions

Posted by dan <da...@bamlabs.com>.
Here's another clue about JspServlet.  Looking through the tomcat sources,
which includes Jasper, I found that they load JspServlet before anything
else.  Here's from their org.apache.catalina.core.StandardWrapper class:

    /**
     * Return the load-on-startup order value (negative value means
     * load on first call).
     */
    public int getLoadOnStartup() {

        if (isJspServlet && loadOnStartup < 0) {
            /*
             * JspServlet must always be preloaded, because its instance is
             * used during registerJMX (when registering the JSP
             * monitoring mbean)
             */
             return Integer.MAX_VALUE;
        } else {
            return (this.loadOnStartup);
        }
    }

I didn't see anything about this in the list. Perhaps I'm running across
this because I'm the first one trying it with native sessions?

Dan


--
View this message in context: http://shiro-user.582556.n2.nabble.com/Using-native-web-sessions-tp6799265p6822446.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Using native web sessions

Posted by dan <da...@bamlabs.com>.
Please ignore the last post.  I was able to resolve it by adding 
    securityManager.sessionMode = native
to my shiro.ini file.  Woops!! 

Anyway, now I can see quite an improvement.  But my app still makes a call
to getSession() outside of shiro.  Here's the debug stack:

http://shiro-user.582556.n2.nabble.com/file/n6821244/stackJspPage.png 

It looks like JSP pages are bypassing the filter.  Does this sound right?

Thanks a lot for all your patience!

Dan



--
View this message in context: http://shiro-user.582556.n2.nabble.com/Using-native-web-sessions-tp6799265p6821244.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Using native web sessions

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

Yes, this approach makes a lot of sense.  It is actually similar to what we
have.  I made a few modifications to our codebase so that the Shiro filter
can be first in line.  First, I got this to work without using shiro native
sessions.  Then I enabled native sessions by adding some lines to shiro.ini. 
The first part of my shiro.ini [main] section looks like:

hazelcastCacheManager = com.security.hazelcast.HazelcastCacheManager

sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
securityManager.sessionManager = $sessionManager
securityManager.sessionManager.sessionDAO = $sessionDAO
sessionIdGenerator = com.security.SimpleSessionIdGenerator
securityManager.sessionManager.sessionDAO.sessionIdGenerator =
$sessionIdGenerator
securityManager.cacheManager = $hazelcastCacheManager

When I run it, I still notice that it will create first tomcat sessionIds,
and then shiro ids.

Here is a stack trace when I break on HttpServletRequestWrapper.getSession()

http://shiro-user.582556.n2.nabble.com/file/n6821089/StackAtGetSessionInOurFilter.png 

It shows that a tomcat sessionId is created.

For a bit more details, on the same page request, here's another stack
trace:

http://shiro-user.582556.n2.nabble.com/file/n6821089/2ndStackLaterOnInSamePageRequest.png 

It shows the request coming in correctly and handled by shiro.

On the first stack trace, my expectation is that the getSession() request in
our app's filter, FxFilter, would cause shiro's sessionId to be generated.

Much thanks,
Dan


--
View this message in context: http://shiro-user.582556.n2.nabble.com/Using-native-web-sessions-tp6799265p6821089.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Using native web sessions

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

What we do is authenticate a user with his password by going to the
database.  Then, we check if he is an "active user" by again going to the
database.  We could have implemented the enable check higher up but by doing
both these checks in shiro, we can have denials handled the same way.  

Thanks !
Dan

--
View this message in context: http://shiro-user.582556.n2.nabble.com/Using-native-web-sessions-tp6799265p6821049.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Using native web sessions

Posted by Les Hazlewood <lh...@apache.org>.
I agree, this is probably the best way to go, but I would go about it
a slightly different way.  Here is what I believe to be the optimal
way of the world when starting up web apps (this is how Shiro 1.2
works now too):

Create a ServletContextListener that performs all necessary
initialization for your app and place something in the ServletContext
that allows you to get access to necessary things at runtime.
Application environment initialization is a separate concern from
filtering requests, so ideally this wouldn't be tightly coupled to
Filter initialization IMO.

For example, in Shiro 1.1 and earlier, the entire Shiro environment
was initialized when the main ShiroFilter was initialized.  Because
initialization was tightly coupled to Filter logic, any component that
_wasn't_ a filter often couldn't get access to things they needed.

Now Shiro init and filtering are nicely decoupled in Shiro 1.2:  a new
ServletContextListener (the
org.apache.shiro.web.env.EnvironmentLoaderListener) initializes Shiro
at app startup and places an Environment object in the ServletContext
to ensure it is available should anything need it.  The ShiroFilter
then references the Shiro Environment object when it needs access to
things during filtering.  Any other application object also now has
access to the Environment object should it need it, even if that
component isn't a Filter or even Shiro-related.

I consider this to be a best practice, even if Shiro wasn't involved.
You could leverage the same benefits in your own app.  I should also
note that this is exactly how Spring web-apps work as well (Shiro's
implementation was based on ideas behind Spring's
ContextLoaderListener), so if you don't want to reinvent the wheel for
your own app, you might want to try it if you're not using it already.
 I'm sure Guice has a similar concept as well.

Finally, with regards to Filter config, I would also like to reiterate
the power of Shiro's filter chains: they can be configured with _any_
javax.servlet.Filter, not just Shiro-specific ones.

In my opinion, the best thing to do is to configure all of your
filters (non Shiro filters too) in the Shiro [main] section if
possible, and reference them in the [urls] section.  Shiro's INI (and
other config formats that may be used like Spring or Guice) are more
convenient than web.xml and much easier to understand what chains look
like instead of interpreting locations in web.xml.

HTH,

-- 
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: Using native web sessions

Posted by Luke Biddell <lu...@gmail.com>.
We have a similar setup, sounds like you need two filters.

First is your application filter - in it's init method it spools up all your
system services (that's about all it does, exception handling maybe but no
certainly no session stuff).
Next you have the standard shiro filter.
Then you write your own shiro filter to use in shiro.ini which deals with
the other stuff. Nice and flexible and you can configure it against any urls
etc.

Luke


On 21 September 2011 01:31, dan <da...@bamlabs.com> wrote:

> Hi Les,
>
> Your idea was right on .. my shiro filter is second in line.  Our
> application has a filter which is first.  The reason shiro is second is
> that
> a number of services need to be initialized in order for shiro to operate.
> Here are some examples to give you a flavor:
>
> 1. We only permit logins if the user is enabled. This boolean is pulled
> from
> the database, so the database subsystem needs to be initialized.
>
> 2. We allow access based on a client's company license.  What we do is go
> to
> the database and retrieve the company license info.
>
> 3. We have properties which we read in from files.  Some of these
> properties
> help in the decision process.
>
> Perhaps our app is "backwards", but can you comment on how you would
> structure an application to support all this?
>
> Many thanks,
> Dan
>
> --
> View this message in context:
> http://shiro-user.582556.n2.nabble.com/Using-native-web-sessions-tp6799265p6814424.html
> Sent from the Shiro User mailing list archive at Nabble.com.
>

Re: Using native web sessions

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

Your idea was right on .. my shiro filter is second in line.  Our
application has a filter which is first.  The reason shiro is second is that
a number of services need to be initialized in order for shiro to operate. 
Here are some examples to give you a flavor:

1. We only permit logins if the user is enabled. This boolean is pulled from
the database, so the database subsystem needs to be initialized.

2. We allow access based on a client's company license.  What we do is go to
the database and retrieve the company license info.

3. We have properties which we read in from files.  Some of these properties
help in the decision process.

Perhaps our app is "backwards", but can you comment on how you would
structure an application to support all this?

Many thanks,
Dan

--
View this message in context: http://shiro-user.582556.n2.nabble.com/Using-native-web-sessions-tp6799265p6814424.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Using native web sessions

Posted by Les Hazlewood <lh...@apache.org>.
There are three things I can think of off the top of my head:

1.  Your ShiroFilter instance does not filter 100% of requests to your
app and something in non-Shiro-Filtered request calls
request.getSession() creating a Servlet Container session.  This is
the most likely culprit.  Ensure that your ShiroFilter filter mapping
is /* and that it sits in front of (above) all other servlet filter
mappings in web.xml.

2.  Your ShiroFilter catches all requests but it is not the first one
in the filter chain.  Maybe there is another filter in front of it in
the filter chain that calls request.getSession(), which would create a
Servlet Container session since the ShiroFilter hasn't executed yet
and wasn't able to intercept the getSession() call and direct it to
its own Session Management mechanism.

3.  If you're using a dynamic framework (e.g. like Grails or something
similar) or even a homegrown framework, filters could be injected in
the filter chain front of the ShiroFilter without you knowing it.

In any event, I'd attach a debugger to your app and stick a breakpoint
on HttpServletRequest.getSession() and
HttpServletRequest.getSession(boolean) to see what in the call stack
is triggering the Servlet Container session.  If you don't see Shiro
in the call stack, then you'll have found what is causing the problem.

Finally, if that still doesn't get you anywhere, please share your
relevant Shiro config so we can look for any 'gotchas'.

HTH!

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

On Thu, Sep 15, 2011 at 5:38 PM, dan <da...@bamlabs.com> wrote:
> Hi --
>
> I'm trying to convert our existing shiro-based web project over to native
> sessions.  This way, I can handle sessions in a clustered server
> environment.
>
> To shiro.ini, I added EnterpriseCacheSessionDAO and set its sessionDAO to a
> CacheManager that I have that uses Hazelcast.  I also specified
> DefaultWebSessionManager.
>
> In web.xml, BamIniShiroFilter is the first filter.
>
> Now, when I go to page with rememberMe, I see a JSESSIONID with the shiro
> format.  Then when I go to another page, it switches to the tomcat format.
>
> When I go to the logon page, it displays JSESSIONID in tomcat's format.
>
> Our application is a bit complex, with a bunch of home-grown stuff and Java
> Server Faces.
>
> I don't understand why any sessions are created with tomcat!  Can you point
> me to how to debug this?
>
> Dan
>
>
> --
> View this message in context: http://shiro-user.582556.n2.nabble.com/Using-native-web-sessions-tp6799265p6799265.html
> Sent from the Shiro User mailing list archive at Nabble.com.