Jeveaux's Weblog
Tudo certo e nada resolvido
Tudo certo e nada resolvido
Segurança sempre soa como uma falácia na maioria dos projetos de software. É como aquele pessoal que não gosta ou não sabe testar: eles sabem que a coisa existe e que é preciso ou muito recomendável a usar, mas no fim das contas dão de ombros e se funcionar funcionou.
Isso acontece muito quando o âmbito é segurança. Qual cliente ou usuário não se preocupa com segurança? Ao menos um controle de acesso com autenticação através de usuário e senha eles sempre exigem. E qualquer desenvolvedor que se preze se preocupa com isso.
Quando pensamos em segurança em aplicações Java temos que conhecer bem como funciona a arquitetura de segurança da plataforma Java, que é bem completa a útil. A divisão se dá em três “áreas” distintas, que são: JCA - Java Cryptography Architecture – Define classes e interfaces que são responsáveis por trabalhar com criptografia e descriptografia de dados e informações; JSSE - Java Secure Socket Extension – Usa a JCA para criar conexões seguras para troca de dados e informações; e JAAS - Java Authentication and Authorization Service – Responsável por autenticação e autorização nas aplicações Java. Neste post vou abordar somente um pouco do JSSE, para saber mais sobre JAAS veja no arquivo do blog.
O SSL (Secure Socket Layer) e o TLS (Transport Layer Security) são protocolos criptográficos usados para garantir a comunicação segura entre serviços de internet. Não vou entrar em detalhes sobre os protocolos e nem nas suas diferenças, para maiores informações sugiro esta leitura.
A necessidade fundamental de uma implementação com SSL é garantir a privacidade e integridade dos dados trafegados entre as aplicações que estão se comunicando. E isso é realizado através da autenticação das aplicações e da utilização de algoritmo criptográfico nos dados que estão sendo trafegados.
Dizer isso é meio bonitinho mas ninguém consegue compreender como isso ocorre de verdade, o que acontece por “por baixo dos panos”. Vamos imaginar um cliente utilizando um browser qualquer para acessar uma aplicação instalada num servidor JBoss, com certificado SSL implantado. Quando a comunicação entre eles é iniciada o servidor envia uma chave pública ao browser, que usa esta chave para criar uma chave privada temporária que é enviada de volta ao servidor. Desta forma as duas partes, servidor e browser, usarão estas chaves para estabelecer uma comunicação segura. Para saber mais sobre chaves públicas, privadas, criptografia simétrica e assimétrica veja a minha apresentação sobre certificação digital.
Vamos então por a mão na massa e configurar a aplicação.
Usaremos o keytool para criar um keystore e nele armazenar as chaves.
1 | keytool -genkey -keystore jeve.keystore -storepass jevepass -keypass jevepass -keyalg RSA -alias jeve_key -validity 3650 -dname "cn=Jeveaux,ou=Jeveaux,c=Vitoria,s=ES,c=BR" |
Detalhamento do comando:
Próximos passos, informar ao JBoss/Tomcat onde está o keystore e qual chave usar.
Basicamente temos que copiar o arquivo do keystore, gerado no passo anterior, para o JBoss. O ideal seria em:
1 | $JBOSS_HOME/server/default/conf |
Trabalharemos agora no arquivo server.xml para configurar qual keystore usar. Este é um arquivo de configuração do Tomcat.
Se você estiver usando JBoss:
1 | $JBOSS_HOME/server/default/deploy/jbossweb.sar/server.xml |
Se estiver usando Tomcat:
1 | $TOMCAT_HOME/conf/server.xml |
Procure por um comentário semelhante a este:
1 2 3 4 | <!-- Define a SSL HTTP/1.1 Connector on port 8443 This connector uses the JSSE configuration, when using APR, the connector should be using the OpenSSL style configuration described in the APR documentation --> |
Haverá um trecho do arquivo comentado logo abaixo, vamos retirar os comentários e ativar este trecho de código. Ajustando as propriedades adequadas chegaremos em algo próximo disso:
1 2 3 4 5 6 7 | <Connector protocol="HTTP/1.1" SSLEnabled="true" port="8443" address="${jboss.bind.address}" maxThreads="100" strategy="ms" maxHttpHeaderSize="8192" emptySessionPath="true" scheme="https" secure="true" clientAuth="false" keystoreFile="${jboss.server.home.dir}/conf/jeve.keystore" keystorePass="jevepass" sslProtocol = "TLS" /> |
Os pontos mais importantes são: port, keystoreFile e keystorePass, que são responsáveis por, respectivamente, definir a porta para utilização do SSL, qual o arquivo contém as chaves e qual a senha do arquivo que contém as chaves.
Neste ponto já conseguimos utilizar a aplicação através do protocolo HTTPS, basta acessar:
1 | https://localhost:8443/aplicacao |
Até aqui a aplicação está disponível tanto através de HTTP quando através de HTTPS. Em algumas situações isso é desejado, em outras não. Existem casos onde precisaremos que algumas partes ou módulos da aplicação só funcionem com HTTPS e outras situações que toda a aplicação responda somente sob HTTPS, e ambas são possíveis de serem atendidas, veremos.
1 2 3 4 5 6 7 8 9 | <security-constraint> <web-resource-collection> <web-resource-name>app-name</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint> |
Inserindo este trecho no seu web.xml nós faremos com que a aplicação inteira responda apenas sob protocolo HTTPS.
Tudo foi feito utilizando um certificado fictício e poderá correr assim durante o desenvolvimento, não há problema algum. Mas em produção este certificado terá o mesmo valor que uma nota de um cruzado novo. Então você, ou sua empresa, farão a aquisição de um certificado válido através de um autoridade certificadora e, quando isso ocorrer importaremos o certificado válido para nosso keystore, utilizando a mesma ferramenta que usamos para criar o certificado anterior (keytool) vejamos:
1 | keytool -import -alias jeve_key -keystore $JBOSS_HOME/server/default/conf/jeve.keystore -trustcacerts -file $ENDERECO_DO_CERTIFICADO_VALIDO/certificado_valido.cer |
E pronto, certificado válido importado e comunicação segura garantida.
9 de maio de 2009 - 10:26
Fala Jeveaux´s blz?
Como diz a Regina Casé : “facim, facim”…
Agora, e pra deixar o os dois protocolos (http e https) respondendo na mesma porta, tem como?
10 de maio de 2009 - 11:35
Luiz,
Eu não estou certo se é possível fazer alguma configuração como esta no JBoss e nem em outro web server. Eu já trabalhei certa vez para fazer o Apache HTTP Server redirecionar as requisições HTTP na porta 80 para HTTPS na porta 443, mas fiz usando o mod_rewrite, foi até relativamente simples. Não é exatamente o que você quer, mas talvez já ajude.
Abraço,
8 de outubro de 2009 - 05:18
Ola Jeveaux,
Muito bom o seu tutorial, no meu caso estou desesperado para fazer uma autenticacao via cliente, ou seja, quero que o cliente so acesse a aplicacao se tiver o devido certificado instalado, ja fiz todos os passos descritos acima, porem usando o keyman para geracao das chaves e keystores, sera que voce poderia me dar uma ajuda? so falta implementar a parte cliente, que nao tenho idéia de como fazer e nao encontro material na net explicando…
Abraços
André