10 Replies Latest reply on May 19, 2002 4:38 PM by hanenkamp

    a different null Principal problem

      First, let me say (to filter out the obvious responses) that I'm very familiar with container based security on both web and ejb tiers, and have successfully done it several times in JBoss for a variety of apps.

      Now, for my problem, which is probably a Tomcat problem but I thought I'd post it here to see if anyone else in the JBoss community has encountered it:

      In Tomcat 3.2.x, securing a url pattern enforces login, and - once successful - a Principal object and a remoteUser String is available via the Request object everywhere on the website.

      In Tomcat 4.0.x, securing a url pattern enforces login properly, BUT once successful - a Principal object and a remoteUser String are ONLY available in the Request object when the user is accessing url patterns that are locked down.

      For example, if I protected /protected/*, once logged in the Principal in 3.2.x would not be null for pages everywhere, both in /protected/* and anywhere else (like /index.jsp).

      However in 4.0.x, I only have a non-null Principal in /protected/*, not anywhere else. This really stinks when you want to have a home page that detects whether a user is already logged in or not depending on whether the Principal is null or not. Unless this gets fixed, I guess it's goodbye to "Welcome, David" on a non-protected page.

      I don't remember seeing anything to do with this in the spec...

      Thanks, all -
      David

        • 1. Re: a different null Principal problem
          starksm64

          You do not say if this behavior is specific to the integrated tomcat4. Does a standalone tomcat using the simple xml file based realm show the same behavior?

          • 2. Re: a different null Principal problem

            Thanks for responding, Scott. Hey, you know what? It works as intended (Principal everywhere after login) in vanilla Tomcat-4.0.2. However, when coming bundled with JBoss-2.4.4, it doesn't...

            Here's what I did - I have two standalone copies of Tomcat 3.2.3 and Tomcat 4.0.2.

            For 3.2.3:
            ----------
            1) cd $TOMCAT3_HOME/webapps/examples/jsp/security/.
            2) cp ./protected/index.jsp ./test.jsp
            3) start tomcat
            4) surf to http://localhost:8080/examples/jsp/security/protected/
            5) after logging in, surf to http://localhost:8080/examples/jsp/security/test.jsp - you will still have a non-null Principal.
            6) stop tomcat

            That works the same for me with my custom app with bundled JBoss-2.4.4_Tocmat-3.2.3.

            For 4.0.2
            ---------
            1) cd $TOMCAT4_HOME/webapps/examples/jsp/security/.
            2) cp ./protected/index.jsp ./test.jsp
            3) start tomcat
            4) surf to http://localhost:8080/examples/jsp/security/protected/
            5) after logging in, surf to http://localhost:8080/examples/jsp/security/test.jsp - you will still have a non-null Principal.
            6) stop tomcat

            That DOES NOT work the same for me with my custom app with bundled JBoss-2.4.4_Tocmat-4.0.1. I also tried replacing the catalina subdir with 4.0.2, but got the same behavior: I lose my request Principal when surfing in non-protected paths, but get it (the same one) back when surfing back to the protected area.

            Thanks again for your help,
            David

            • 3. Re: a different null Principal problem
              starksm64

              The issue here is that when tomcat is embedded into JBoss caching of principal information at the tomcat level is disabled. This was necessary to ensure that the JBossSecurityMgrRealm is called on every request that needs authentication to avoid leaking security information associated with the request thread. Its not clear from the servlet spec where getUserPrincipal must return a non-null value. I have submitted question to the servlet list on this topic.

              • 4. Re: a different null Principal problem
                starksm64

                The reply I got on the servlet interest list was that when getUserPrincipal should or should not return null is not currently defined. The only guarenteed context in which getUserPrincipal will not be null is under a secured path with tomcat embedded in JBoss.

                • 5. Re: a different null Principal problem

                  Thanks for looking into this, but then how am I supposed to get the username on pages in non-protected paths? I guess I could shove it into the HTTPSession after a successful log in but that sounds real hacky.

                  • 6. Re: a different null Principal problem
                    starksm64

                    Your going to have to do it in an application specific way. Using a session or a cookie would be one way.

                    • 7. Re: a different null Principal problem

                      Got it to work by using HttpSession (yuck). Thanks for your help, Scott. Though I've worked around it, my opinion is that (in light of spec fuzziness), it should work in Tomcat4 just like it did in Tomcat3. Might as well err toward the status quo, so to speak. Thanks again.

                      • 8. Re: a different null Principal problem
                        lychan

                        Can you elaborate how you did it with httpsession.

                        My understanding of the web container managed security is that the login page will come up the first you hit a protected resource, and after authentication (using j_security_check), it redirect backs to the page you are trying to access.

                        So, did you find a way to intercept it to stick attribute in the httpsession after j_security_check but before going to the actual page, or you use a filter, or you have codes in every protected page/resource?

                        Yes, I agree that it would be nicer if getUserPrincipal() will return the actual principal if the user has actually logged on instead of null for unprotected resources. Makes it much easier to have dynamic menus or output depending on user role.

                        Rgds
                        Leonard

                        • 9. Re: a different null Principal problem

                          Sure. In our application, no user accesses JSP's directly. There is a single "control" Servlet that gathers request params and delegates to EJBs to do work. Based on the success/failure of that work, the Servlet uses a workflow manager to forward to a particular screen (jsp page).

                          Now, since every request goes through the same Servlet, after a user logs in using container managed security I grab the request.getRemoteUser() and throw it into the HttpSession. So from then on if a user hits an unprotected resource I can still tell if he/she is logged in by checking the remoteUser (username) I put into the HttpSession. When the user logs out, I invalidate the HttpSession which effectively blows away the stored username.

                          The only thing this doesn't cover is roles, as there is no way in the servlet api to gather all the roles for a user. Only a way (via the request) to tell if they are in a specified role or not. The way that I got around this is again attributed to the fact that all requests go through the same control servlet. I just make sure if they are going to access a path where I want to check on a role that I make sure they get redirected to a path that is protected by the container.

                          Hope this helps,
                          David

                          • 10. Re: a different null Principal problem
                            hanenkamp

                            I have a problem with this feature/bug. In fact, the whole servlet 2.3 security specification and integration with J2EE has me rather peeved. It doesn't take into account a lot of obvious things. Anyway, I digress...

                            My problem is, very similar to dward2. I am designing a general content management system and I need to be able to programmatically authenticate to the J2EE server. The system itself does not directly support EJBs at this time as I wish the system to be relatively free of data/logic bindings and leave such things up to the desires of the plugin writers/deployers of the system. However, I would like to perform authentication through the J2EE ssrver so that restricted EJBs may be used.

                            However, the system also maintains its own security settings independent of the servlet container and verifies roles programmatically. Upon attempt to access a restricted resource, the client is forwarded to a "return" page that is declaratively restricted in the web.xml file. Then, the user is forwarded to a login screen, logs in and the user now has a role allowing him to access the "return" page which then sends the user back to the first request--which is on an unrestricted page. So, as this discussion indicates, my code only works if unrestricted pages also show the user logged in.

                            I believe I have a couple possible solutions, under JBoss, for this problem. One is to keep a user under some restricted URL after login until logout. Or two, restrict all pages, but only by a "Guest" role which will be granted by some custom LoginManager. I consider both solutions to be hacks and wandered if anyone had a better idea?

                            Thanks,
                            Sterling