Preloader image

Este é um simples exemplo sobre como utilizar JNDI com restrições de segurança para o TomEE.

Contrato

No nosso exemplo, Contract é uma interface anotada com @Remote a qual indica que todos os métodos desta interface podem ser acessados por um código em um cliente.

	@Remote
	public interface Contract {
	    String hi();
	}

Implementação de contrato

ContractImpl é uma implementação da interface Contract restringindo o acesso ao método hi para usuários com a permissão test.

public class ContractImpl implements Contract {
    @Override
    @RolesAllowed("test")
    public String hi() {
        return "hi";
    }
}

Teste de contrato

Nesta classe, nós testamos nossa aplicação com Arquillian criando um war, com as classes do contrato e sua implementação, e fazendo o deploy para um servidor TomEE embutido com o nome test.war. No arquivo arquillian.xml especificamos que o arquillian utiliza o arquivo tomcat-users.xml na pasta src/test/conf. No arquivo tomcat-users.xml existe um único usuário com o nome de usuário "tomcat", senha "users" and permissão "test".

Para testar, nós procuramos pela ContractImpl e chamamos o método hi usando diferentes nomes de usuários e senhas.

@RunWith(Arquillian.class)
public class ContractTest {
    @Deployment(testable = false)
    public static Archive<?> app() {
        return ShrinkWrap.create(WebArchive.class, "test.war")
                .addClasses(Contract.class, ContractImpl.class);
    }

    @ArquillianResource
    private URL base;

    @Test
    public void valid() throws NamingException {
        assertEquals("hi", hi(new Properties() {{
            setProperty(Context.INITIAL_CONTEXT_FACTORY, RemoteInitialContextFactory.class.getName());
            setProperty(Context.PROVIDER_URL, String.format("http://localhost:%s/tomee/ejb", base.getPort()));
            setProperty(Context.SECURITY_PRINCIPAL, "tomcat");
            setProperty(Context.SECURITY_CREDENTIALS, "users");
        }}));
    }

    @Test
    public void invalid() throws NamingException {
        try {
            hi(new Properties() {{
                setProperty(Context.INITIAL_CONTEXT_FACTORY, RemoteInitialContextFactory.class.getName());
                setProperty(Context.PROVIDER_URL, String.format("http://localhost:%s/tomee/ejb", base.getPort()));
                setProperty(Context.SECURITY_PRINCIPAL, "tomcat");
                setProperty(Context.SECURITY_CREDENTIALS, "wrong");
            }});
            fail();
        } catch (final AuthenticationException ae) {
            // ok
        }
    }

    @Test
    public void missingCredentials() throws NamingException {
        try {
            hi(new Properties() {{
                setProperty(Context.INITIAL_CONTEXT_FACTORY, RemoteInitialContextFactory.class.getName());
                setProperty(Context.PROVIDER_URL, String.format("http://localhost:%s/tomee/ejb", base.getPort()));
            }});
            fail();
        } catch (final EJBAccessException eae) {
            // no-op
        }
    }

    private String hi(final Properties clientConfig) throws NamingException {
        return Contract.class.cast(new InitialContext(clientConfig).lookup("java:global/test/ContractImpl!org.superbiz.Contract")).hi();
    }
}

Rodando a aplicação

mvn install

Todos os casos de testes irão passar.