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 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 e ú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;
- JAAS (Java Authentication and Authorization Service): Responsável por autenticação e autorização nas aplicações Java.
Neste artigo 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 a 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.
Criando as chaves
Usaremos o keytool para criar um keystore e nele armazenar as chaves.
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:
- keytool: comando
- -genkey: parâmetro para criação das chaves
- -keystore: indica o caminho/nome do keystore (jeve.keystore)
- -storepass: indica a senha do keystore (jevepass)
- -keypass: indica a senha da chave (jevepass)
- -keyalg: indica o algoritmo de criptografia utilizado (RSA)
- -alias: indica o nome da chave a ser criada dentro do keystore (jeve_key)
- -validity: Validade do certificado em dias (3650)
- -dname “[…]”: Informações do certificado (CN =
nome comum, OU = unidade organizacional (departamento, divisão), O =
nome da organização, L = nome da localidade (cidade), S = estado, C =
código do país)
Próximos passos, informar ao JBoss/Tomcat onde está o keystore e qual chave usar.
Instalando as chaves
Basicamente temos que copiar o arquivo do keystore, gerado no passo anterior, para o JBoss. O ideal seria em:
$JBOSS_HOME/server/default/confConfigurando o JBoss ou o Tomcat
Trabalharemos agora no arquivo server.xml para configurar qual keystore usar. Este é um arquivo de configuração do Tomcat.
Se você estiver usando JBoss:
$JBOSS_HOME/server/default/deploy/jbossweb.sar/server.xmlSe estiver usando Tomcat:
$TOMCAT_HOME/conf/server.xmlProcure por um comentário semelhante a este:
<!-- Define a SSL HTTP/1.1 Connector on port 8443<br />This connector uses the JSSE configuration, when using APR, the<br />connector should be using the OpenSSL style configuration<br />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:
<Connector protocol="HTTP/1.1" SSLEnabled="true"<br /> port="8443" address="${jboss.bind.address}"<br /> maxThreads="100" strategy="ms" maxHttpHeaderSize="8192"<br /> emptySessionPath="true"<br /> scheme="https" secure="true" clientAuth="false"<br /> keystoreFile="${jboss.server.home.dir}/conf/jeve.keystore"<br /> 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:
https://localhost:8443/aplicacaoConfigurando a aplicação
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.
<security-constraint><br /> <web-resource-collection><br /> <web-resource-name>app-name</web-resource-name><br /> <url-pattern>/*</url-pattern><br /> </web-resource-collection><br /> <user-data-constraint><br /> <transport-guarantee>CONFIDENTIAL</transport-guarantee><br /> </user-data-constraint><br /> </security-constraint>Inserindo este trecho no seu web.xml nós faremos com que a aplicação inteira responda apenas sob protocolo HTTPS.
Importando um certificado válido
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:
keytool -import -alias jeve_key -keystore $JBOSS_HOME/server/default/conf/jeve.keystore -trustcacerts -file $ENDERECO_DO_CERTIFICADO_VALIDO/certificado_valido.cerE, pronto, certificado válido importado e comunicação segura garantida.







