@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; }
@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; }