PDA

View Full Version : Supported Way to Emulate request.getUserPrincipal?



sethladd
Feb 3rd, 2005, 05:38 PM
Hello,

I'm trying to migrate our application to use Acegi. I can't seem to find a supported way for request.getUserPrincipal to work. Is there a filter impl that wraps a normal HttpServletRequest with one that would make getUserPrincipal return info?

Thanks very much,
Seth

adepue
Feb 3rd, 2005, 05:50 PM
IIRC, I believe this is handled by container integration. Basically, custom integration code for each type of container (Tomcat, JBoss, WebLogic, etc) must be maintained. I'm not sure what the status of this maintenance is for Acegi. At one point it was bundled with Acegi, but it may have been split off by now. At any rate, it is handled by a filter (filters extending AbstractIntegrationFilter in my version of Acegi). In the worst case you would have to end up extending AbstractIntegrationFilter yourself to integrate with your container - but I bet this wouldn't be too hard.

- Andy

sethladd
Feb 3rd, 2005, 06:05 PM
Thanks your your reply!

I was under the impression that the container integration code was useful when you needed the container to do the authentication.

I have migrated to Acegi for Authentication, so I have a SecureContext available to me. I wanted to get that into the HttpServletRequest to ease migration, porting, and to keep Acegi code out of my Servlets and Controllers. I think this is the opposite intent of the container integration code (where you have a good request.getUserPrincipal, but you need to push into a SecureContext).

Of course, I could be totally wrong here. I'll double check now. :)

In any case, I did end up creating a simple filter that creates a HttpServletRequestWrapper and replaces the calls to getUserPrincipal, isUserInRole, etc with methods that delegate to my SecureContext and Authentication objects.

It seems like this would be very useful, especially as it brings Acegi closer to a "drop-in" replacement for container auth. I'd be happy to donate this (very simple) code.

sethladd
Feb 3rd, 2005, 06:26 PM
The simple wrapper for the HttpServletRequest seems to be working quite well. I'd love any feedback, and if so, for this to be included in the next release of Acegi. I think it's a great step forward to making it possible for Acegi to be a "drop-in" replacement.



import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext;

/**
* Wraps a normal <code>HttpServletRequest</code> with a
* &#123;@link AuthenticationHttpServletRequest&#125;.
* <p/>
* This helps with transparent migration from old container managed code
* that relied on calls such as <code>request.getUserPrincipal</code> to
* the Acegi framework.
*/
public class AuthenticationWrapperFilter implements Filter &#123;

/**
* @see javax.servlet.Filter#init&#40;javax.servlet.FilterConf ig&#41;
*/
public void init&#40;FilterConfig arg0&#41; throws ServletException &#123; &#125;

/**
* @see javax.servlet.Filter#doFilter&#40;javax.servlet.Servle tRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain&#41;
*/
public void doFilter&#40;ServletRequest req, ServletResponse res,
FilterChain chain&#41; throws IOException, ServletException &#123;
SecureContext ctx = &#40;SecureContext&#41; ContextHolder.getContext&#40;&#41;;
ServletRequest oldReq = null;

if &#40;isValidContext&#40;ctx&#41;&#41; &#123;
oldReq = req;
req = new AuthenticationHttpServletRequest&#40;&#40;HttpServletReque st&#41;req&#41;;
&#125;

chain.doFilter&#40;req, res&#41;;

if &#40;isValidContext&#40;ctx&#41;&#41; &#123;
req = oldReq;
&#125;
&#125;

/**
* @param ctx the current context
* @return <code>true</code> if the context is not null and it has an
* <code>Authentication</code> object, or <code>false</code>
*/
private boolean isValidContext&#40;SecureContext ctx&#41; &#123;
return ctx != null && ctx.getAuthentication&#40;&#41; != null;
&#125;

/**
* @see javax.servlet.Filter#destroy&#40;&#41;
*/
public void destroy&#40;&#41; &#123; &#125;

&#125;




import java.security.Principal;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext;

/**
* Wraps a normal <code>HttpServletRequest</code> to delegate Principal
* related methods to the <code>Authentication</code> object that lives
* in the <code>SecureContext</code> of the current Thread.
* <p/>
* This helps with transparent migration from old container managed code
* that relied on calls such as <code>request.getUserPrincipal</code> to
* the Acegi framework.
*/
public class AuthenticationHttpServletRequest extends HttpServletRequestWrapper &#123;

private Authentication auth;

/**
* @param request the original request
*/
public AuthenticationHttpServletRequest&#40;HttpServletReques t request&#41; &#123;
super&#40;request&#41;;
SecureContext ctx = &#40;SecureContext&#41; ContextHolder.getContext&#40;&#41;;
auth = ctx.getAuthentication&#40;&#41;;
&#125;

/**
* @see javax.servlet.http.HttpServletRequest#getRemoteUse r&#40;&#41;
*/
public String getRemoteUser&#40;&#41; &#123;
return auth.getName&#40;&#41;;
&#125;

/**
* @see javax.servlet.http.HttpServletRequest#getUserPrinc ipal&#40;&#41;
*/
public Principal getUserPrincipal&#40;&#41; &#123;
return auth;
&#125;

/**
* @see javax.servlet.http.HttpServletRequest#isUserInRole &#40;java.lang.String&#41;
*/
public boolean isUserInRole&#40;String roleName&#41; &#123;
if &#40;roleName == null&#41; return false;

GrantedAuthority&#91;&#93; roles = auth.getAuthorities&#40;&#41;;
for &#40;int i = 0; i < roles.length; i++&#41; &#123;
if &#40;roleName.equals&#40;roles&#91;i&#93;.getAuthority&#40;&#41;&#41;&#41; &#123;
return true;
&#125;
&#125;

return false;
&#125;
&#125;

Ben Alex
Feb 4th, 2005, 03:49 AM
Folks, it's already in release 0.7.0! :-)

Take a look in the net.sf.acegisecurity.ui.wrapper package. Sorry I didn't get to this post sooner and could have saved you some coding.

adepue
Feb 4th, 2005, 10:03 AM
Boy, not only was I wrong to begin with, but the code is there in the latest version. Well, thought oughta teach me not to shoot off the hip. :)

- Andy

sethladd
Feb 4th, 2005, 11:58 AM
Thanks Ben!

I knew it had to be in there, just haven't learned the package layout of Acegi yet.

Migrating over to the supported code now. :)

sethladd
Feb 4th, 2005, 12:17 PM
Hi Ben,

I took a look at ContextHolderAwareRequestWrapper. It doesn't override getUserPrincipal. I think we can easily provide an implementation for it, by returning the Authentication (which itself is a Principal).

What do you think?

Thanks,
Seth

ps I tried to sign up for the developers list, but never received my confirmation. Will try again.

Ben Alex
Feb 5th, 2005, 12:25 AM
For the benefit of the forum archives, Seth sent in a contribution for this functionality. The patch was added to CVS today.

Peter Bohm
Mar 7th, 2005, 07:08 PM
Hi all,
can anybody give me a hint how it's implemented in version 0.8.

My code was working fine with 0.7, but after I upgraded to 0.8 the isUserInRole doesn't work anymore.

I added filter ContextHolderAwareRequestFilter - and it works correctly - but only in the filter itself. When UserRoleAuthorizationInterceptor is called the isUserInRole returns false for everything...

Thanks

Peter

sethladd
Mar 7th, 2005, 07:24 PM
Did you change the order of your filters? Maybe another filter farther down the chain is re-wrapping the Request object?

Peter Bohm
Mar 7th, 2005, 08:25 PM
Hi Seth,
yes...I did that - I tried it at every possible order - from first to last but it didn't work.
(The ony difference was that when it ContextHolderAwareRequestFilter was first in the chain it didn't have any acegi context)

Peter

Peter Bohm
Mar 8th, 2005, 09:03 PM
I'm still not able to figure out how to use the ContextHolderAwareRequestFilter as a part of FilterChainProxy....so at the moment I just call it directly from web.xml (just like in version 0.7).

Please let me know If anybody has any suggestions on how to implement it using the filter chain proxy :-)

Thanks

Peter

sethladd
Mar 9th, 2005, 12:00 PM
Peter,

Can you post your config?

Thanks,
Seth

Ben Alex
Mar 10th, 2005, 05:03 AM
ContextHolderAwareRequestFilter integration with FilterChainProxy could well be a bug, as Matt also noticed in http://forum.springframework.org/viewtopic.php?t=3933. I promise to look at it ASAP. In the meantime I would expect you can continue to use it via FilterToBeanProxy (ie outside FilterChainProxy).

Peter Bohm
Mar 10th, 2005, 05:59 AM
Hi Ben,
thanks for answer and pointing to Matt's thread...he nicely summed up my last Saturday :-)
First the logging out and then the filter chain...

Peter

Ben Alex
Mar 10th, 2005, 07:45 PM
FilterChainProxy is now fixed and in CVS.