Announcement Announcement Module
Collapse
No announcement yet.
Supported Way to Emulate request.getUserPrincipal? Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Supported Way to Emulate request.getUserPrincipal?

    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

  • #2
    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

    Comment


    • #3
      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.

      Comment


      • #4
        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.

        Code:
        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.FilterConfig&#41;
             */
            public void init&#40;FilterConfig arg0&#41; throws ServletException &#123; &#125;
        
            /**
             * @see javax.servlet.Filter#doFilter&#40;javax.servlet.ServletRequest, 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;HttpServletRequest&#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;
        Code:
        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;HttpServletRequest 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#getRemoteUser&#40;&#41;
             */
            public String getRemoteUser&#40;&#41; &#123;
                return auth.getName&#40;&#41;;
            &#125;
            
            /**
             * @see javax.servlet.http.HttpServletRequest#getUserPrincipal&#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;

        Comment


        • #5
          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.

          Comment


          • #6
            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

            Comment


            • #7
              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.

              Comment


              • #8
                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.

                Comment


                • #9
                  For the benefit of the forum archives, Seth sent in a contribution for this functionality. The patch was added to CVS today.

                  Comment


                  • #10
                    How does it work in 0.8?

                    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

                    Comment


                    • #11
                      Did you change the order of your filters? Maybe another filter farther down the chain is re-wrapping the Request object?

                      Comment


                      • #12
                        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

                        Comment


                        • #13
                          ContextHolderAwareRequestFilter in 0.8

                          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

                          Comment


                          • #14
                            Peter,

                            Can you post your config?

                            Thanks,
                            Seth

                            Comment


                            • #15
                              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).

                              Comment

                              Working...
                              X