You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Antony Bowesman <ad...@teamware.com> on 2001/05/04 08:54:39 UTC

Realm implementations

Hi,

In TC 3.x authenticate() method of a realm is called for every request. 
(I gather this is changed in 4.x).  

I am implementing a JAAS Realm which authenticates against a back end
EJB user realm.  I want to avoid this authentication for every request
so I have done the following in authenticate()

authenticate()
{
   ...
   JAASRealmPrincipal principal = new
              JAASRealmPrincipal(principalName, lc.getSubject());
   //  Set principal into Tomcat
   req.setUserPrincipal(principal);
   ...
}

so, now if I call getUserPrincipal() I get my JAAS realm that now sits
inside tomcat's RequestImpl.

In 3.2.2b1 the req.getUserPrincipal() method created a SimplePrincipal
if the principal was null so it never returned null.

In 3.2.2b4 it is changed (same as 3.3) and now returns null if there is
no principal.  So, it is sufficient to do this in authenticate()?

--------------------
   if (req.setUserPrincipal(principal) == null)
   {
       // User not authenticated... do authentication
       ...
       JAASRealmPrincipal principal = new
                 JAASRealmPrincipal(principalName, lc.getSubject());
       //  Set principal into Tomcat
       req.setUserPrincipal(principal);
       ...
   }
   else
       // User already authenticated...
       return true;
--------------------

I am assuming the RequestImpl is a per HTTP session object.  Is this
correct?  So, each different HTTP session will get a different
RequestImpl?

If so, when HTTP session times out the authentication for that user is
lost.  Is it possible to keep the HTTP session alive beyond the
configured timeout through some keep alive mechanism?  I have a logical
session that is container independent and there may have been activity
on that session that is not related to the HTTP session and so I want to
prevent Tomcat from losing the authenticated context. 

How does this fit into TC4?

Best regards
Antony

-- 
Antony Bowesman
Teamware Group 
adb@teamware.com
tel: +358 9 5128 2562
fax: +358 9 5128 2705

Re: Realm implementations

Posted by Antony Bowesman <ad...@teamware.com>.
Craig,

Thanks for your comments.

"Craig R. McClanahan" wrote:
> 
> On Fri, 4 May 2001, Antony Bowesman wrote:
> 
> > Hi,
> >
> > In TC 3.x authenticate() method of a realm is called for every request.
> > (I gather this is changed in 4.x).
> >
> 
> You are correct.  Tomcat 4 caches the user Principal object returned
> by the authenticate() method in the user's session.  If the
> application calls request.isUserInRole() -- or the container is
> enforcing security constraints -- you may or may not have to go
> back to the underlying security realm to look up the role
> information, depending on how you've implemented things.  All
> the current Realm implementations cache the assigned roles along
> with the user Principal as well.

Will you be adding a cachable JAAS Subject or LoginContext into TC4 at
any stage, this would move it a little closer to JAAS? 

> > I am assuming the RequestImpl is a per HTTP session object.  Is
> > this correct?  So, each different HTTP session will get a
> > different RequestImpl?
> >
> 
> Actually, RequestImpl is per *request*, not per *session*.  In
> Tomcat 4, the caching actually happens in the session implementation
> object (it's in the internal Tomcat part of the API).
> 
> > If so, when HTTP session times out the authentication for that
> > user is lost.  Is it possible to keep the HTTP session alive
> > beyond the configured timeout through some keep alive mechanism?
> > I have a logical session that is container independent and there
> > may have been activity on that session that is not related to
> > the HTTP session and so I want to prevent Tomcat from losing the
> > authenticated context.
> >
> 
> Keeping the session alive (beyond the normal timeout mechanism)
> would require tweaking the way that Tomcat does session expiration.
> 
> If you want to keep something alive beyond the lifetime of a
> session, it sounds like you might need to store the actual objects
> elsewhere (perhaps in a collection stored as a session context 
> attribute), and maintain references to them as session attributes.
> You could use HttpSessionBindingListener events to know when session
> references to the underlying "EJB session" objects are added or 
> subtracted.  This would also let you share an EJB session across
> multiple HTTP sessions, if that was appropriate for your
> requirements.

Actually, our session is an 'overlying' session.  It is not specific to
any container and is available in ORB, EJB, WEB or standalone Java app
so I guess we will set session timeout to -1 and allow our session to
invalidate the HttpSession when it times out.

Rgds
Antony

-- 
Antony Bowesman
Teamware Group 
adb@teamware.com
tel: +358 9 5128 2562
fax: +358 9 5128 2705

Re: Realm implementations

Posted by "Craig R. McClanahan" <cr...@apache.org>.

On Fri, 4 May 2001, Antony Bowesman wrote:

> Hi,
> 
> In TC 3.x authenticate() method of a realm is called for every request. 
> (I gather this is changed in 4.x).  
> 

You are correct.  Tomcat 4 caches the user Principal object returned by
the authenticate() method in the user's session.  If the application calls
request.isUserInRole() -- or the container is enforcing security
constraints -- you may or may not have to go back to the underlying
security realm to look up the role information, depending on how you've
implemented things.  All the current Realm implementations cache the
assigned roles along with the user Principal as well.

> I am implementing a JAAS Realm which authenticates against a back end
> EJB user realm.  I want to avoid this authentication for every request
> so I have done the following in authenticate()
> 
> authenticate()
> {
>    ...
>    JAASRealmPrincipal principal = new
>               JAASRealmPrincipal(principalName, lc.getSubject());
>    //  Set principal into Tomcat
>    req.setUserPrincipal(principal);
>    ...
> }
> 
> so, now if I call getUserPrincipal() I get my JAAS realm that now sits
> inside tomcat's RequestImpl.
> 
> In 3.2.2b1 the req.getUserPrincipal() method created a SimplePrincipal
> if the principal was null so it never returned null.
> 
> In 3.2.2b4 it is changed (same as 3.3) and now returns null if there is
> no principal.  So, it is sufficient to do this in authenticate()?
> 
> --------------------
>    if (req.setUserPrincipal(principal) == null)
>    {
>        // User not authenticated... do authentication
>        ...
>        JAASRealmPrincipal principal = new
>                  JAASRealmPrincipal(principalName, lc.getSubject());
>        //  Set principal into Tomcat
>        req.setUserPrincipal(principal);
>        ...
>    }
>    else
>        // User already authenticated...
>        return true;
> --------------------
> 
> I am assuming the RequestImpl is a per HTTP session object.  Is this
> correct?  So, each different HTTP session will get a different
> RequestImpl?
> 

Actually, RequestImpl is per *request*, not per *session*.  In Tomcat 4,
the caching actually happens in the session implementation object (it's in
the internal Tomcat part of the API).

> If so, when HTTP session times out the authentication for that user is
> lost.  Is it possible to keep the HTTP session alive beyond the
> configured timeout through some keep alive mechanism?  I have a logical
> session that is container independent and there may have been activity
> on that session that is not related to the HTTP session and so I want to
> prevent Tomcat from losing the authenticated context. 
> 

Keeping the session alive (beyond the normal timeout mechanism) would
require tweaking the way that Tomcat does session expiration.

If you want to keep something alive beyond the lifetime of a session, it
sounds like you might need to store the actual objects elsewhere (perhaps
in a collection stored as a session context attribute), and maintain
references to them as session attributes.  You could use
HttpSessionBindingListener events to know when session references to the
underlying "EJB session" objects are added or subtracted.  This would also
let you share an EJB session across multiple HTTP sessions, if that was
appropriate for your requirements.


> How does this fit into TC4?
> 

Pretty much the same, although the caching of user principals is already
done for you in the Authenticator implementations.

> Best regards
> Antony
> 

Craig McClanahan



Re: Realm implementations

Posted by Antony Bowesman <ad...@teamware.com>.
Hi Costin,

Thanks for your comments.

cmanolache@yahoo.com wrote:
> 
> Hi Antony,
> 
> > In TC 3.x authenticate() method of a realm is called for every
> > request.
> 
> Well, yes and no.
> 
> The BaseInterceptor.authenticate() callback is called on every request
> ( as it is on Apache and other servers ).
> 
> The authenticate method of the realm ( that goes to a database or
> does expensive operations ) should be called once - and the result
> cached by the module ( either in session, or in a local cache ).
> We don't do this for the simple realm - but we should.

When you talk about caching it in the session I would understand that I
need to call req.getSession(true) to ensure a session is available. 
With form authentication the session is present as the j_* fields are in
it but for BASIC there is no session so I will have to create one.  I'd
rather not cache in the realm as I then have to start worrying about
cleaning out old authentications when the HttpSessio expires.

> A particular case is the authentication module - I expect tomcat
> to be "integrated" in different systems, and I doubly the "simple
> realm" will be used for anything but development. So there is no
> point in optimizing it,

Agreed.

> I would rather spend time on specialized modules that can be
> used in production environment ( and JAAS is probably the most
> important one, since it could be integrated with PAM and give
> access to most auth schemes).

Yes, it seems Tomcat has to move towards directly supporting JAAS as
that is the way J2EE 1.3 and JDK1.4 are moving.

> Another big priority is a module
> that delegates the auth to apache - but we have to wait for
> ajp14 for that.
> 
> > I am implementing a JAAS Realm which authenticates against a back end
> > EJB user realm.  I want to avoid this authentication for every request
> > so I have done the following in authenticate()
> 
> I would cache it inside the session ( if any ) - that's the most
> common case ( most people use sessions and authentication ).
> 
> If you want to deal with the 10% special cases you could maintain
> a local cache to avoid calling the JAAS for each request.
> 
> > In 3.2.2b4 it is changed (same as 3.3) and now returns null if there is
> > no principal.  So, it is sufficient to do this in authenticate()?
> 
> I think that's the correct behavior.
> 
> > I am assuming the RequestImpl is a per HTTP session object.  Is this
> > correct?  So, each different HTTP session will get a different
> > RequestImpl?
> 
> No, that's almost impossible. The session is detected long after the
> request is received ( and you could have cases where you have
> multiple requests on the same time in the same session - think about a
> page with images ). You need to use req.getSession(false).
> 
> (and keep in mind that authentication doesn't require session, even if
> most of the time they are used togheter !)
> 
> > If so, when HTTP session times out the authentication for that user is
> > lost.  Is it possible to keep the HTTP session alive beyond the
> > configured timeout through some keep alive mechanism?  I have a logical
> > session that is container independent and there may have been activity
> > on that session that is not related to the HTTP session and so I want to
> > prevent Tomcat from losing the authenticated context.
> 
> I don't know if it would be a good idea. If you really want to keep the
> security context longer you should use your own cache, and let the session
> work as it is supposed to.
> 
> ( and it shouldn't be very difficult ).
> 
> Please let us know how this project evolves - I'm very interested in JAAS
> authentication for tomcat, as an add-on module.
> 
> Costin

Best regards
Antony
-- 
Antony Bowesman
Teamware Group 
adb@teamware.com
tel: +358 9 5128 2562
fax: +358 9 5128 2705

Re: Realm implementations

Posted by cm...@yahoo.com.
Hi Antony,


> In TC 3.x authenticate() method of a realm is called for every request. 

Well, yes and no.

The BaseInterceptor.authenticate() callback is called on every request
( as it is on Apache and other servers ). 

The authenticate method of the realm ( that goes to a database or does
expensive operations ) should be called once - and the result cached by
the module ( either in session, or in a local cache ). We don't do this
for the simple realm - but we should.

In general, up to 3.3 most of the focus in 3.x was in optimizing and
simplifying the core and giving flexibility and power to modules. Most
individual modules are not optimized yet.

The good news is that new modules can be added to 3.3 quite easily - and
without worry about the ( extremely long so far ) release
cycle. 

A particular case is the authentication module - I expect tomcat to be
"integrated" in different systems, and I doubly the "simple realm" will be
used for anything but development. So there is no point in optimizing it,
I would rather spend time on specialized modules that can be used in
production environment ( and JAAS is probably the most important one,
since it could be integrated with PAM and give access to most auth
schemes). Another big priority is a module that delegates the auth to
apache - but we have to wait for ajp14 for that.


> I am implementing a JAAS Realm which authenticates against a back end
> EJB user realm.  I want to avoid this authentication for every request
> so I have done the following in authenticate()

I would cache it inside the session ( if any ) - that's the most common
case ( most people use sessions and authentication ).

If you want to deal with the 10% special cases you could maintain a local
cache to avoid calling the JAAS for each request. 

> In 3.2.2b4 it is changed (same as 3.3) and now returns null if there is
> no principal.  So, it is sufficient to do this in authenticate()?

I think that's the correct behavior.

> I am assuming the RequestImpl is a per HTTP session object.  Is this
> correct?  So, each different HTTP session will get a different
> RequestImpl?

No, that's almost impossible. The session is detected long after the
request is received ( and you could have cases where you have
multiple requests on the same time in the same session - think about a
page with images ). You need to use req.getSession(false).

(and keep in mind that authentication doesn't require session, even if
most of the time they are used togheter !)

> If so, when HTTP session times out the authentication for that user is
> lost.  Is it possible to keep the HTTP session alive beyond the
> configured timeout through some keep alive mechanism?  I have a logical
> session that is container independent and there may have been activity
> on that session that is not related to the HTTP session and so I want to
> prevent Tomcat from losing the authenticated context. 

I don't know if it would be a good idea. If you really want to keep the
security context longer you should use your own cache, and let the session
work as it is supposed to. 

( and it shouldn't be very difficult ).


Please let us know how this project evolves - I'm very interested in JAAS
authentication for tomcat, as an add-on module. 

Costin