This is an automated email from the ASF dual-hosted git repository. radcortez pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomee.git
commit 200a84e80586d85319de19a7ecfb08fc69243c17 Author: Roberto Cortez <[email protected]> AuthorDate: Thu Dec 27 12:31:49 2018 +0000 TOMEE-2365 - Initial implementation and wiring of FormAuthenticationMechanism. --- .../security/cdi/FormAuthenticationMechanism.java | 48 +++++++++++++ .../tomee/security/cdi/TomEESecurityExtension.java | 81 +++++++++++++++------- ...curityServletAuthenticationMechanismMapper.java | 7 ++ .../security/servlet/FormAuthServletTest.java | 81 ++++++++++++++++++++++ 4 files changed, 192 insertions(+), 25 deletions(-) diff --git a/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/FormAuthenticationMechanism.java b/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/FormAuthenticationMechanism.java new file mode 100644 index 0000000..b7a29e8 --- /dev/null +++ b/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/FormAuthenticationMechanism.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomee.security.cdi; + +import javax.enterprise.context.ApplicationScoped; +import javax.security.enterprise.AuthenticationException; +import javax.security.enterprise.AuthenticationStatus; +import javax.security.enterprise.authentication.mechanism.http.HttpAuthenticationMechanism; +import javax.security.enterprise.authentication.mechanism.http.HttpMessageContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@ApplicationScoped +public class FormAuthenticationMechanism implements HttpAuthenticationMechanism { + @Override + public AuthenticationStatus validateRequest(final HttpServletRequest request, final HttpServletResponse response, + final HttpMessageContext httpMessageContext) + throws AuthenticationException { + throw new UnsupportedOperationException(); + } + + @Override + public AuthenticationStatus secureResponse(final HttpServletRequest request, final HttpServletResponse response, + final HttpMessageContext httpMessageContext) + throws AuthenticationException { + throw new UnsupportedOperationException(); + } + + @Override + public void cleanSubject(final HttpServletRequest request, final HttpServletResponse response, + final HttpMessageContext httpMessageContext) { + throw new UnsupportedOperationException(); + } +} diff --git a/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityExtension.java b/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityExtension.java index 712587e..91036c9 100644 --- a/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityExtension.java +++ b/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityExtension.java @@ -31,51 +31,82 @@ import javax.enterprise.inject.spi.BeanManager; import javax.enterprise.inject.spi.BeforeBeanDiscovery; import javax.enterprise.inject.spi.Extension; import javax.enterprise.inject.spi.ProcessAnnotatedType; +import javax.enterprise.inject.spi.WithAnnotations; import javax.security.enterprise.authentication.mechanism.http.BasicAuthenticationMechanismDefinition; +import javax.security.enterprise.authentication.mechanism.http.FormAuthenticationMechanismDefinition; import javax.security.enterprise.authentication.mechanism.http.HttpAuthenticationMechanism; import java.util.HashSet; import java.util.Set; public class TomEESecurityExtension implements Extension { private final Set<AnnotatedType> basicAuthentication = new HashSet<>(); + private final Set<AnnotatedType> formAuthentication = new HashSet<>(); - void processAuthenticationMechanismDefinitions(@Observes final ProcessAnnotatedType<?> processAnnotatedType) { + void observeBeforeBeanDiscovery(@Observes final BeforeBeanDiscovery beforeBeanDiscovery, + final BeanManager beanManager) { + beforeBeanDiscovery.addAnnotatedType(beanManager.createAnnotatedType(DefaultAuthenticationMechanism.class)); + beforeBeanDiscovery.addAnnotatedType( + beanManager.createAnnotatedType(TomEESecurityServletAuthenticationMechanismMapper.class)); + beforeBeanDiscovery.addAnnotatedType(beanManager.createAnnotatedType(TomEEDefaultIdentityStore.class)); + beforeBeanDiscovery.addAnnotatedType(beanManager.createAnnotatedType(TomEEIdentityStoreHandler.class)); + } + + void processAuthenticationMechanismDefinitions(@Observes + @WithAnnotations({ + BasicAuthenticationMechanismDefinition.class, + FormAuthenticationMechanismDefinition.class + }) final ProcessAnnotatedType<?> processAnnotatedType) { final AnnotatedType<?> annotatedType = processAnnotatedType.getAnnotatedType(); + if (annotatedType.isAnnotationPresent(BasicAuthenticationMechanismDefinition.class)) { basicAuthentication.add(annotatedType); } - } - void observeBeforeBeanDiscovery(@Observes final BeforeBeanDiscovery beforeBeanDiscovery, - final BeanManager beanManager) { - if (basicAuthentication.isEmpty()) { - beforeBeanDiscovery.addAnnotatedType(beanManager.createAnnotatedType(DefaultAuthenticationMechanism.class)); - beforeBeanDiscovery.addAnnotatedType( - beanManager.createAnnotatedType(TomEESecurityServletAuthenticationMechanismMapper.class)); - beforeBeanDiscovery.addAnnotatedType(beanManager.createAnnotatedType(TomEEDefaultIdentityStore.class)); - beforeBeanDiscovery.addAnnotatedType(beanManager.createAnnotatedType(TomEEIdentityStoreHandler.class)); + if (annotatedType.isAnnotationPresent(FormAuthenticationMechanismDefinition.class)) { + formAuthentication.add(annotatedType); } } void registerAuthenticationMechanism(@Observes final AfterBeanDiscovery afterBeanDiscovery, final BeanManager beanManager) { if (!basicAuthentication.isEmpty()) { - afterBeanDiscovery.addBean() - .id(BasicAuthenticationMechanism.class.getName()) - .beanClass(BasicAuthenticationMechanism.class) - .types(Object.class, HttpAuthenticationMechanism.class, BasicAuthenticationMechanism.class) - .qualifiers(Default.Literal.INSTANCE, Any.Literal.INSTANCE) - .scope(ApplicationScoped.class) - .createWith((CreationalContext<BasicAuthenticationMechanism> creationalContext) -> { - AnnotatedType<BasicAuthenticationMechanism> annotatedType = - beanManager.createAnnotatedType(BasicAuthenticationMechanism.class); - BeanAttributes<BasicAuthenticationMechanism> beanAttributes = - beanManager.createBeanAttributes(annotatedType); - return beanManager.createBean(beanAttributes, BasicAuthenticationMechanism.class, - beanManager.getInjectionTargetFactory(annotatedType)) - .create(creationalContext); - }); + afterBeanDiscovery + .addBean() + .id(BasicAuthenticationMechanism.class.getName()) + .beanClass(BasicAuthenticationMechanism.class) + .types(Object.class, HttpAuthenticationMechanism.class, BasicAuthenticationMechanism.class) + .qualifiers(Default.Literal.INSTANCE, Any.Literal.INSTANCE) + .scope(ApplicationScoped.class) + .createWith((CreationalContext<BasicAuthenticationMechanism> creationalContext) -> { + AnnotatedType<BasicAuthenticationMechanism> annotatedType = + beanManager.createAnnotatedType(BasicAuthenticationMechanism.class); + BeanAttributes<BasicAuthenticationMechanism> beanAttributes = + beanManager.createBeanAttributes(annotatedType); + return beanManager.createBean(beanAttributes, BasicAuthenticationMechanism.class, + beanManager.getInjectionTargetFactory(annotatedType)) + .create(creationalContext); + }); } + + if (!formAuthentication.isEmpty()) { + afterBeanDiscovery + .addBean() + .id(FormAuthenticationMechanism.class.getName()) + .beanClass(FormAuthenticationMechanism.class) + .types(Object.class, HttpAuthenticationMechanism.class, FormAuthenticationMechanism.class) + .qualifiers(Default.Literal.INSTANCE, Any.Literal.INSTANCE) + .scope(ApplicationScoped.class) + .createWith((CreationalContext<FormAuthenticationMechanism> creationalContext) -> { + AnnotatedType<FormAuthenticationMechanism> annotatedType = + beanManager.createAnnotatedType(FormAuthenticationMechanism.class); + BeanAttributes<FormAuthenticationMechanism> beanAttributes = + beanManager.createBeanAttributes(annotatedType); + return beanManager.createBean(beanAttributes, FormAuthenticationMechanism.class, + beanManager.getInjectionTargetFactory(annotatedType)) + .create(creationalContext); + }); + } + } public boolean hasAuthenticationMechanisms() { diff --git a/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityServletAuthenticationMechanismMapper.java b/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityServletAuthenticationMechanismMapper.java index 836fff4..fff782e 100644 --- a/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityServletAuthenticationMechanismMapper.java +++ b/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityServletAuthenticationMechanismMapper.java @@ -22,6 +22,7 @@ import javax.enterprise.event.Observes; import javax.enterprise.inject.spi.CDI; import javax.inject.Inject; import javax.security.enterprise.authentication.mechanism.http.BasicAuthenticationMechanismDefinition; +import javax.security.enterprise.authentication.mechanism.http.FormAuthenticationMechanismDefinition; import javax.security.enterprise.authentication.mechanism.http.HttpAuthenticationMechanism; import javax.servlet.ServletContext; import javax.servlet.ServletRegistration; @@ -44,6 +45,12 @@ public class TomEESecurityServletAuthenticationMechanismMapper { servletAuthenticationMapper.put(servletName, CDI.current().select(BasicAuthenticationMechanism.class).get()); } + + if (servletClass.isAnnotationPresent(FormAuthenticationMechanismDefinition.class)) { + servletAuthenticationMapper.put(servletName, + CDI.current().select(FormAuthenticationMechanism.class).get()); + } + } catch (final ClassNotFoundException e) { // Ignore } diff --git a/tomee/tomee-security/src/test/java/org/apache/tomee/security/servlet/FormAuthServletTest.java b/tomee/tomee-security/src/test/java/org/apache/tomee/security/servlet/FormAuthServletTest.java new file mode 100644 index 0000000..9881c5f --- /dev/null +++ b/tomee/tomee-security/src/test/java/org/apache/tomee/security/servlet/FormAuthServletTest.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomee.security.servlet; + +import org.junit.Test; + +import javax.enterprise.context.ApplicationScoped; +import javax.security.enterprise.authentication.mechanism.http.FormAuthenticationMechanismDefinition; +import javax.security.enterprise.authentication.mechanism.http.LoginToContinue; +import javax.servlet.ServletException; +import javax.servlet.annotation.HttpConstraint; +import javax.servlet.annotation.ServletSecurity; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.client.ClientBuilder; +import java.io.IOException; + +import static org.junit.Assert.assertEquals; + +public class FormAuthServletTest extends AbstractTomEESecurityTest { + @Test + public void authenticate() throws Exception { + final String servlet = "http://localhost:" + container.getConfiguration().getHttpPort() + "/form"; + assertEquals(200, ClientBuilder.newBuilder().build() + .target(servlet) + .request() + .get().getStatus()); + } + + @ApplicationScoped + @FormAuthenticationMechanismDefinition( + loginToContinue = @LoginToContinue() + ) + public static class ApplicationAuthentication { + + } + + @WebServlet(urlPatterns = "/login") + public static class LoginServlet extends HttpServlet { + @Override + protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) + throws ServletException, IOException { + + } + } + + @WebServlet(urlPatterns = "/login-error") + public static class ErrorServlet extends HttpServlet { + @Override + protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) + throws ServletException, IOException { + + } + } + + @WebServlet(urlPatterns = "/form") + @ServletSecurity(@HttpConstraint(rolesAllowed = "tomcat")) + public static class TestServlet extends HttpServlet { + @Override + protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) + throws ServletException, IOException { + resp.getWriter().write("ok!"); + } + } +}
