8 Replies Latest reply on Oct 2, 2013 1:22 PM by swiderski.maciej

    Strange behavior with PolicyContext and obtaining HttpServletRequest

    steve_167

      SETUP:

       

      I deploy multiple WARs, some of which are protected by a custom security domain with a custom JAAS login module as defined in the JBoss AS configuration file and some of which are unsecured.  The login module JAR for the login module that protects the secured webapps is contained in its own JBoss user-defined module.  In the login module the PolicyContext is leveraged to obtain the current HttpServletRequest as follows:

       

      HttpServletRequest request = (HttpServletRequest)PolicyContext.getContext("javax.servlet.http.HttpServletRequest");

       

       

      PROBLEM:

       

      If I deploy all the WARs, the login module works as expected and there are no problems.  HOWEVER, if I undeploy ANY of the WARs and a new user comes along to any of the other secured web applications, the above line of code to obtain the servlet request results in the following exception:

       

      13:03:35,335 ERROR [org.jboss.security.authentication.JBossCachedAuthenticationManager] (ajp--0.0.0.0-8009-1) Login failure: javax.security.auth.login.LoginException: java.lang.IllegalArgumentException: No PolicyContextHandler for key=javax.servlet.http.HttpServletRequest

          at javax.security.jacc.PolicyContext.getContext(PolicyContext.java:117)

       

      If I then redeploy ANY of the web applications, the problems goes away.  It's only on undeployment -- and it doesn't matter whether the webapp I undeploy is a secured or unsecured web application.

       

       

      THOUGHTS:

       

      It seems like the policy context handler for the request is being deregistered whenever any WAR is undeployed and then reregistered upon deployment of any webapp.

       

      Any ideas?  I might file this as a bug with JBoss AS.

       

       

       

      Edit:  I got a chance to grep the JBoss 7 trunk codebase to see where PolicyContext handler registration occurs and this was the only thing I found.  It looks like the JBossWebRealmService is responsible for this.

       

      $ find . -type f -name "*.java" -exec grep "PolicyContext.register" {} \; -print

                  PolicyContext.registerHandler(SecurityConstants.SUBJECT_CONTEXT_KEY, handler, true);

                  PolicyContext.registerHandler(SecurityConstants.CALLBACK_HANDLER_KEY, chandler, true);

      ./security/src/main/java/org/jboss/as/security/service/SecurityBootstrapService.java

                  PolicyContext.registerHandler(SecurityConstants.WEB_REQUEST_KEY, handler, true);

      ./web/src/main/java/org/jboss/as/web/security/JBossWebRealmService.java

        • 1. Re: Strange behavior with PolicyContext and obtaining HttpServletRequest
          steve_167

          So I took a look at that class and sure enough there is a removal of the HttpServletRequestPolicyContextHandler in the stop lifecycle method:

           

          package org.jboss.as.web.security;

           

          import java.util.Set;

           

          import javax.security.jacc.PolicyContext;

           

          import org.apache.catalina.Realm;

          import org.jboss.as.security.plugins.SecurityDomainContext;

          import org.jboss.as.server.deployment.DeploymentUnit;

          import org.jboss.msc.inject.Injector;

          import org.jboss.msc.service.Service;

          import org.jboss.msc.service.StartContext;

          import org.jboss.msc.service.StartException;

          import org.jboss.msc.service.StopContext;

          import org.jboss.msc.value.InjectedValue;

          import org.jboss.security.SecurityConstants;

           

          /**

          * Service to install the default {@code Realm} implementation.

          *

          * @author <a href="mailto:mmoyses@redhat.com">Marcus Moyses</a>

          */

          public class JBossWebRealmService implements Service<Realm> {

           

              private volatile Realm realm;

           

              private final InjectedValue<SecurityDomainContext> securityDomainContextValue = new InjectedValue<SecurityDomainContext>();

           

              private final DeploymentUnit deploymentUnit;

           

              public JBossWebRealmService(DeploymentUnit deploymentUnit) {

                  this.deploymentUnit = deploymentUnit;

              }

           

              /** {@inheritDoc} */

              @Override

              public void start(StartContext context) throws StartException {

                  JBossWebRealm jbossWebRealm = new JBossWebRealm();

                  SecurityDomainContext sdc = securityDomainContextValue.getValue();

                  jbossWebRealm.setAuthenticationManager(sdc.getAuthenticationManager());

                  jbossWebRealm.setAuthorizationManager(sdc.getAuthorizationManager());

                  jbossWebRealm.setMappingManager(sdc.getMappingManager());

                  jbossWebRealm.setAuditManager(sdc.getAuditManager());

                  jbossWebRealm.setDeploymentUnit(deploymentUnit);

                  this.realm = jbossWebRealm;

                  try {

                      // Register the active request PolicyContextHandler

                      HttpServletRequestPolicyContextHandler handler = new HttpServletRequestPolicyContextHandler();

                      PolicyContext.registerHandler(SecurityConstants.WEB_REQUEST_KEY, handler, true);

                  } catch (Exception e) {

                      throw new StartException(e);

                  }

              }

           

              /** {@inheritDoc} */

              @SuppressWarnings("rawtypes")

              @Override

              public void stop(StopContext context) {

                  realm = null;

                  // remove handler

                  Set handlerKeys = PolicyContext.getHandlerKeys();

                  handlerKeys.remove(SecurityConstants.WEB_REQUEST_KEY);

              }

           

              /** {@inheritDoc} */

              @Override

              public Realm getValue() throws IllegalStateException, IllegalArgumentException {

                  return realm;

              }

           

              /**

               * Target {@code Injector}

               *

               * @return target

               */

              public Injector<SecurityDomainContext> getSecurityDomainContextInjector() {

                  return securityDomainContextValue;

              }

           

          }

           

           

           

           

          It almost seems as if this PolicyContext class exists in the same classloader for ALL webapps(or is being resolved from the system classloader) and is being adversely impacted by any/all webapps.

          • 2. Re: Strange behavior with PolicyContext and obtaining HttpServletRequest
            steve_167

            Just for the record, I don't want to imply that I know for sure that the above class has its start/stop lifecycle methods invoked for every web application as it's deployed/undeployed respectively.  I simply don't know enough about the design.  But searching through the entire JBoss 7 codebase only yielded this single reference to removing the HttpServletRequestPolicyContextHandler.

             

            /** {@inheritDoc} */

                @SuppressWarnings("rawtypes")

                @Override

                public void stop(StopContext context) {

                    realm = null;

                    // remove handler

                    Set handlerKeys = PolicyContext.getHandlerKeys();

                    handlerKeys.remove(SecurityConstants.WEB_REQUEST_KEY);

                }

             

            What puzzles me is I still don't see how this would be executed even for unsecured webapps with no reference to any security domain.

            • 3. Re: Strange behavior with PolicyContext and obtaining HttpServletRequest
              steve_167

              So I can confirm that the culprit is in fact this stop method.  It is executed for every web application.  I commented-out this code as follows just to test(and may keep it):

               

              /** {@inheritDoc} */

                  @SuppressWarnings("rawtypes")

                  @Override

                  public void stop(StopContext context) {

                      realm = null;

                      // remove handler

                      /**

                      Set handlerKeys = PolicyContext.getHandlerKeys();

                      handlerKeys.remove(SecurityConstants.WEB_REQUEST_KEY);

                      */

                  }

               

              then removed the one JBossWebRealmService.class file from the JAR and rebuilt this single class from the 7.1.1 source.  The JAR I removed the .class from is:

               

              jboss-as-security-7.1.1.Final.jar

               

              the dependencies for building this one class are the remaining classes in the above JAR and:

               

              jboss-msc-1.0.2.GA.jar

              jboss-jacc-api_1.4_spec-1.0.1.Final.jar

              jboss-as-security-7.1.1.Final.jar

              jbossweb-7.0.13.Final.jar

              jboss-as-server-7.1.1.Final.jar

              picketbox-4.0.7.Final.jar

               

              These JARs are all from their respective modules in JBoss 7.1.1. 

               

               

              I'm NOT SUGGESTING THAT THIS IS CORRECT JUST YET OR ANYONE ELSE SHOULD DO THIS but it is a workaround.  I'd really like to know if this is a bug.

              • 4. Re: Strange behavior with PolicyContext and obtaining HttpServletRequest
                steve_167
                • 5. Re: Strange behavior with PolicyContext and obtaining HttpServletRequest
                  ctomc

                  Hi,

                  can you try reproducing this on wildfly 8 alpha 1?

                  wildfly 8 comes with completly new web server undertow.

                   

                  also, 7.1.1 is really old, did you try with 7.2.0.final/eap6.1.alpha

                  • 6. Re: Strange behavior with PolicyContext and obtaining HttpServletRequest
                    steve_167

                    I can try this out with the above mentioned versions when I get back to work on Monday.

                    • 7. Re: Strange behavior with PolicyContext and obtaining HttpServletRequest
                      steve_167

                      So I was able to try this out against WildFly 8.0.0.Alpha1 running the jboss web subsystem(which appears to be newer though than the version included with JBoss 7.1.1.Final).  I can confirm that the same undesired behavior is present and results in the same exception.

                       

                      I was not able to test the newer undertow subsystem in WildFly at this time.  I should have time in the next day or so to do so.

                      • 8. Re: Strange behavior with PolicyContext and obtaining HttpServletRequest
                        swiderski.maciej

                        I can confirm this happens as well on EAP6.1 which in general makes the application server single app because as soon as you undeploy one of the applications other apps that rely on the PolicyContext to provide request will fail.