@Override
  public void deploy() {
    DeploymentInfo deploymentInfo = originalDeployment.clone();

    if (deploymentInfo.getServletStackTraces() == ServletStackTraces.ALL) {
      UndertowServletLogger.REQUEST_LOGGER.servletStackTracesAll(
          deploymentInfo.getDeploymentName());
    }

    deploymentInfo.validate();
    final ConvergedDeploymentImpl deployment =
        new ConvergedDeploymentImpl(this, deploymentInfo, servletContainer);

    // set deployment to parent using reflection
    try {
      Field deploymentField = DeploymentManagerImpl.class.getDeclaredField("deployment");
      deploymentField.setAccessible(true);
      deploymentField.set(this, deployment);
      deploymentField.setAccessible(false);
    } catch (NoSuchFieldException | IllegalAccessException e) {
      throw new RuntimeException(e);
    }

    final ServletContextImpl servletContexImpl =
        new ServletContextImpl(servletContainer, deployment);
    final ServletContext servletContext = new ConvergedServletContextImpl(servletContexImpl);

    // deployment.setServletContext(((ConvergedServletContextImpl)servletContext).getDelegatedContext());
    this.invokeDeploymentMethod(
        deployment,
        "setServletContext",
        new Class[] {ServletContextImpl.class},
        new Object[] {((ConvergedServletContextImpl) servletContext).getDelegatedContext()});
    deployment.setConvergedServletContext((ConvergedServletContextImpl) servletContext);

    handleExtensions(deploymentInfo, servletContext);

    deployment.setDefaultCharset(Charset.forName(deploymentInfo.getDefaultEncoding()));

    handleDeploymentSessionConfig(
        deploymentInfo, ((ConvergedServletContextImpl) servletContext).getDelegatedContext());

    // deployment.setSessionManager(deploymentInfo.getSessionManagerFactory().createSessionManager(deployment));
    this.invokeDeploymentMethod(
        deployment,
        "setSessionManager",
        new Class[] {SessionManager.class},
        new Object[] {deploymentInfo.getSessionManagerFactory().createSessionManager(deployment)});

    deployment
        .getSessionManager()
        .setDefaultSessionTimeout(deploymentInfo.getDefaultSessionTimeout());
    for (SessionListener listener : deploymentInfo.getSessionListeners()) {
      deployment.getSessionManager().registerSessionListener(listener);
    }

    final List<ThreadSetupAction> setup = new ArrayList<>();
    setup.add(ServletRequestContextThreadSetupAction.INSTANCE);
    setup.add(new ContextClassLoaderSetupAction(deploymentInfo.getClassLoader()));
    setup.addAll(deploymentInfo.getThreadSetupActions());
    final CompositeThreadSetupAction threadSetupAction = new CompositeThreadSetupAction(setup);
    deployment.setThreadSetupAction(threadSetupAction);

    ThreadSetupAction.Handle handle = threadSetupAction.setup(null);
    try {

      final ApplicationListeners listeners = createListeners();
      listeners.start();

      // deployment.setApplicationListeners(listeners);
      this.invokeDeploymentMethod(
          deployment,
          "setApplicationListeners",
          new Class[] {ApplicationListeners.class},
          new Object[] {listeners});

      // now create the servlets and filters that we know about. We can still get more later
      createServletsAndFilters(deployment, deploymentInfo);

      // first run the SCI's
      for (final ServletContainerInitializerInfo sci :
          deploymentInfo.getServletContainerInitializers()) {
        final InstanceHandle<? extends ServletContainerInitializer> instance =
            sci.getInstanceFactory().createInstance();
        try {
          instance.getInstance().onStartup(sci.getHandlesTypes(), servletContext);
        } finally {
          instance.release();
        }
      }

      deployment
          .getSessionManager()
          .registerSessionListener(
              new ConvergedSessionListenerBridge(
                  threadSetupAction, listeners, servletContext, deployment.getSessionManager()));

      initializeErrorPages(deployment, deploymentInfo);
      initializeMimeMappings(deployment, deploymentInfo);
      initializeTempDir(servletContext, deploymentInfo);
      listeners.contextInitialized();
      // run

      HttpHandler wrappedHandlers = ServletDispatchingHandler.INSTANCE;
      wrappedHandlers =
          wrapHandlers(wrappedHandlers, deploymentInfo.getInnerHandlerChainWrappers());
      HttpHandler securityHandler = setupSecurityHandlers(wrappedHandlers);
      wrappedHandlers =
          new PredicateHandler(DispatcherTypePredicate.REQUEST, securityHandler, wrappedHandlers);

      HttpHandler outerHandlers =
          wrapHandlers(wrappedHandlers, deploymentInfo.getOuterHandlerChainWrappers());
      wrappedHandlers =
          new PredicateHandler(DispatcherTypePredicate.REQUEST, outerHandlers, wrappedHandlers);
      wrappedHandlers =
          handleDevelopmentModePersistentSessions(
              wrappedHandlers, deploymentInfo, deployment.getSessionManager(), servletContext);

      MetricsCollector metrics = deploymentInfo.getMetricsCollector();
      if (metrics != null) {
        wrappedHandlers = new MetricsChainHandler(wrappedHandlers, metrics, deployment);
      }

      final ServletInitialHandler servletInitialHandler =
          SecurityActions.createServletInitialHandler(
              deployment.getServletPaths(),
              wrappedHandlers,
              deployment.getThreadSetupAction(),
              servletContext);

      HttpHandler initialHandler =
          wrapHandlers(
              servletInitialHandler,
              deployment.getDeploymentInfo().getInitialHandlerChainWrappers());
      initialHandler = new HttpContinueReadHandler(initialHandler);
      if (deploymentInfo.getUrlEncoding() != null) {
        initialHandler =
            Handlers.urlDecodingHandler(deploymentInfo.getUrlEncoding(), initialHandler);
      }
      deployment.setInitialHandler(initialHandler);

      // deployment.setServletHandler(servletInitialHandler);
      this.invokeDeploymentMethod(
          deployment,
          "setServletHandler",
          new Class[] {ServletInitialHandler.class},
          new Object[] {servletInitialHandler});

      deployment.getServletPaths().invalidate(); // make sure we have a fresh set of servlet paths
      ((ConvergedServletContextImpl) servletContext).initDone();
    } catch (Exception e) {
      throw new RuntimeException(e);
    } finally {
      handle.tearDown();
    }

    // set state using reflection:
    try {
      Field stateField = DeploymentManagerImpl.class.getDeclaredField("state");
      stateField.setAccessible(true);
      stateField.set(this, State.DEPLOYED);
      stateField.setAccessible(false);
    } catch (NoSuchFieldException | IllegalAccessException e) {
      throw new RuntimeException(e);
    }
  }
  private HttpHandler setupSecurityHandlers(HttpHandler initialHandler) {
    final DeploymentInfo deploymentInfo = super.getDeployment().getDeploymentInfo();
    final LoginConfig loginConfig = deploymentInfo.getLoginConfig();

    final Map<String, AuthenticationMechanismFactory> factoryMap =
        new HashMap<>(deploymentInfo.getAuthenticationMechanisms());
    if (!factoryMap.containsKey(BASIC_AUTH)) {
      factoryMap.put(BASIC_AUTH, BasicAuthenticationMechanism.FACTORY);
    }
    if (!factoryMap.containsKey(FORM_AUTH)) {
      factoryMap.put(FORM_AUTH, ServletFormAuthenticationMechanism.FACTORY);
    }
    if (!factoryMap.containsKey(DIGEST_AUTH)) {
      factoryMap.put(DIGEST_AUTH, DigestAuthenticationMechanism.FACTORY);
    }
    if (!factoryMap.containsKey(CLIENT_CERT_AUTH)) {
      factoryMap.put(CLIENT_CERT_AUTH, ClientCertAuthenticationMechanism.FACTORY);
    }
    if (!factoryMap.containsKey(ExternalAuthenticationMechanism.NAME)) {
      factoryMap.put(ExternalAuthenticationMechanism.NAME, ExternalAuthenticationMechanism.FACTORY);
    }
    HttpHandler current = initialHandler;
    current = new SSLInformationAssociationHandler(current);

    final SecurityPathMatches securityPathMatches = buildSecurityConstraints();
    current = new ServletAuthenticationCallHandler(current);
    if (deploymentInfo.isDisableCachingForSecuredPages()) {
      current =
          Handlers.predicate(Predicates.authRequired(), Handlers.disableCache(current), current);
    }
    if (!securityPathMatches.isEmpty()) {
      current = new ServletAuthenticationConstraintHandler(current);
    }
    current =
        new ServletConfidentialityConstraintHandler(
            deploymentInfo.getConfidentialPortManager(), current);
    if (!securityPathMatches.isEmpty()) {
      current = new ServletSecurityConstraintHandler(securityPathMatches, current);
    }
    List<AuthenticationMechanism> authenticationMechanisms = new LinkedList<>();
    authenticationMechanisms.add(
        new CachedAuthenticatedSessionMechanism()); // TODO: does this really need to be hard coded?

    String mechName = null;
    if (loginConfig != null || deploymentInfo.getJaspiAuthenticationMechanism() != null) {

      // we don't allow multipart requests, and always use the default encoding
      FormParserFactory parser =
          FormParserFactory.builder(false)
              .addParser(
                  new FormEncodedDataDefinition()
                      .setDefaultEncoding(deploymentInfo.getDefaultEncoding()))
              .build();

      List<AuthMethodConfig> authMethods = Collections.<AuthMethodConfig>emptyList();
      if (loginConfig != null) {
        authMethods = loginConfig.getAuthMethods();
      }

      for (AuthMethodConfig method : authMethods) {
        AuthenticationMechanismFactory factory = factoryMap.get(method.getName());
        if (factory == null) {
          throw UndertowServletMessages.MESSAGES.unknownAuthenticationMechanism(method.getName());
        }
        if (mechName == null) {
          mechName = method.getName();
        }

        final Map<String, String> properties = new HashMap<>();
        properties.put(
            AuthenticationMechanismFactory.CONTEXT_PATH, deploymentInfo.getContextPath());
        properties.put(AuthenticationMechanismFactory.REALM, loginConfig.getRealmName());
        properties.put(AuthenticationMechanismFactory.ERROR_PAGE, loginConfig.getErrorPage());
        properties.put(AuthenticationMechanismFactory.LOGIN_PAGE, loginConfig.getLoginPage());
        properties.putAll(method.getProperties());

        String name = method.getName().toUpperCase(Locale.US);
        // The mechanism name is passed in from the HttpServletRequest interface as the name
        // reported needs to be
        // comparable using '=='
        name = name.equals(FORM_AUTH) ? FORM_AUTH : name;
        name = name.equals(BASIC_AUTH) ? BASIC_AUTH : name;
        name = name.equals(DIGEST_AUTH) ? DIGEST_AUTH : name;
        name = name.equals(CLIENT_CERT_AUTH) ? CLIENT_CERT_AUTH : name;

        authenticationMechanisms.add(factory.create(name, parser, properties));
      }
    }

    ((DeploymentImpl) super.getDeployment()).setAuthenticationMechanisms(authenticationMechanisms);
    // if the JASPI auth mechanism is set then it takes over
    if (deploymentInfo.getJaspiAuthenticationMechanism() == null) {
      current = new AuthenticationMechanismsHandler(current, authenticationMechanisms);
    } else {
      current =
          new AuthenticationMechanismsHandler(
              current,
              Collections.<AuthenticationMechanism>singletonList(
                  deploymentInfo.getJaspiAuthenticationMechanism()));
    }

    current =
        new CachedAuthenticatedSessionHandler(current, super.getDeployment().getServletContext());
    List<NotificationReceiver> notificationReceivers = deploymentInfo.getNotificationReceivers();
    if (!notificationReceivers.isEmpty()) {
      current = new NotificationReceiverHandler(current, notificationReceivers);
    }

    // TODO - A switch to constraint driven could be configurable, however before we can support
    // that with servlets we would
    // need additional tracking within sessions if a servlet has specifically requested that
    // authentication occurs.
    SecurityContextFactory contextFactory = deploymentInfo.getSecurityContextFactory();
    if (contextFactory == null) {
      contextFactory = SecurityContextFactoryImpl.INSTANCE;
    }
    current =
        new SecurityInitialHandler(
            AuthenticationMode.PRO_ACTIVE,
            deploymentInfo.getIdentityManager(),
            mechName,
            contextFactory,
            current);
    return current;
  }
예제 #3
0
  @Override
  public void deploy() {
    final DeploymentInfo deploymentInfo = originalDeployment.clone();

    if (deploymentInfo.getServletStackTraces() == ServletStackTraces.ALL) {
      UndertowServletLogger.REQUEST_LOGGER.servletStackTracesAll(
          deploymentInfo.getDeploymentName());
    }

    deploymentInfo.validate();
    final DeploymentImpl deployment = new DeploymentImpl(this, deploymentInfo, servletContainer);
    this.deployment = deployment;

    final List<ThreadSetupHandler> setup = new ArrayList<>();
    setup.add(ServletRequestContextThreadSetupAction.INSTANCE);
    setup.add(new ContextClassLoaderSetupAction(deploymentInfo.getClassLoader()));
    setup.addAll(deploymentInfo.getThreadSetupActions());
    deployment.setThreadSetupActions(setup);

    final ServletContextImpl servletContext = new ServletContextImpl(servletContainer, deployment);
    deployment.setServletContext(servletContext);
    handleExtensions(deploymentInfo, servletContext);
    deployment.getServletPaths().setWelcomePages(deploymentInfo.getWelcomePages());

    deployment.setDefaultCharset(Charset.forName(deploymentInfo.getDefaultEncoding()));

    handleDeploymentSessionConfig(deploymentInfo, servletContext);

    deployment.setSessionManager(
        deploymentInfo.getSessionManagerFactory().createSessionManager(deployment));
    deployment
        .getSessionManager()
        .setDefaultSessionTimeout(deploymentInfo.getDefaultSessionTimeout());

    try {
      deployment
          .createThreadSetupAction(
              new ThreadSetupHandler.Action<Void, Object>() {
                @Override
                public Void call(HttpServerExchange exchange, Object ignore) throws Exception {
                  final ApplicationListeners listeners = createListeners();
                  listeners.start();

                  deployment.setApplicationListeners(listeners);

                  // now create the servlets and filters that we know about. We can still get more
                  // later
                  createServletsAndFilters(deployment, deploymentInfo);

                  // first run the SCI's
                  for (final ServletContainerInitializerInfo sci :
                      deploymentInfo.getServletContainerInitializers()) {
                    final InstanceHandle<? extends ServletContainerInitializer> instance =
                        sci.getInstanceFactory().createInstance();
                    try {
                      instance.getInstance().onStartup(sci.getHandlesTypes(), servletContext);
                    } finally {
                      instance.release();
                    }
                  }

                  deployment
                      .getSessionManager()
                      .registerSessionListener(
                          new SessionListenerBridge(deployment, listeners, servletContext));
                  for (SessionListener listener : deploymentInfo.getSessionListeners()) {
                    deployment.getSessionManager().registerSessionListener(listener);
                  }

                  initializeErrorPages(deployment, deploymentInfo);
                  initializeMimeMappings(deployment, deploymentInfo);
                  initializeTempDir(servletContext, deploymentInfo);
                  listeners.contextInitialized();
                  // run

                  HttpHandler wrappedHandlers = ServletDispatchingHandler.INSTANCE;
                  wrappedHandlers =
                      wrapHandlers(wrappedHandlers, deploymentInfo.getInnerHandlerChainWrappers());
                  if (!deploymentInfo.isSecurityDisabled()) {
                    HttpHandler securityHandler = setupSecurityHandlers(wrappedHandlers);
                    wrappedHandlers =
                        new PredicateHandler(
                            DispatcherTypePredicate.REQUEST, securityHandler, wrappedHandlers);
                  }
                  HttpHandler outerHandlers =
                      wrapHandlers(wrappedHandlers, deploymentInfo.getOuterHandlerChainWrappers());
                  wrappedHandlers =
                      new PredicateHandler(
                          DispatcherTypePredicate.REQUEST, outerHandlers, wrappedHandlers);
                  wrappedHandlers =
                      handleDevelopmentModePersistentSessions(
                          wrappedHandlers,
                          deploymentInfo,
                          deployment.getSessionManager(),
                          servletContext);

                  MetricsCollector metrics = deploymentInfo.getMetricsCollector();
                  if (metrics != null) {
                    wrappedHandlers = new MetricsChainHandler(wrappedHandlers, metrics, deployment);
                  }
                  if (deploymentInfo.getCrawlerSessionManagerConfig() != null) {
                    wrappedHandlers =
                        new CrawlerSessionManagerHandler(
                            deploymentInfo.getCrawlerSessionManagerConfig(), wrappedHandlers);
                  }

                  final ServletInitialHandler servletInitialHandler =
                      SecurityActions.createServletInitialHandler(
                          deployment.getServletPaths(),
                          wrappedHandlers,
                          deployment,
                          servletContext);

                  HttpHandler initialHandler =
                      wrapHandlers(
                          servletInitialHandler,
                          deployment.getDeploymentInfo().getInitialHandlerChainWrappers());
                  initialHandler = new HttpContinueReadHandler(initialHandler);
                  if (deploymentInfo.getUrlEncoding() != null) {
                    initialHandler =
                        Handlers.urlDecodingHandler(
                            deploymentInfo.getUrlEncoding(), initialHandler);
                  }
                  deployment.setInitialHandler(initialHandler);
                  deployment.setServletHandler(servletInitialHandler);
                  deployment
                      .getServletPaths()
                      .invalidate(); // make sure we have a fresh set of servlet paths
                  servletContext.initDone();
                  return null;
                }
              })
          .call(null, null);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
    state = State.DEPLOYED;
  }