Torne seus aplicativos do Tomcat mais seguros com SSL e Spring Security
Criando uma key store
A primeira coisa que você precisa é de um chaveiro privado contendo um certificado válido, e a forma mais simples de gerar um é utilizando o utilitário keytool do Java localizado no seu diretório $JAVA_HOME/bin.
1
|
keytool -genkey - alias MyKeyAlias -keyalg RSA -keystore /Users/Roger/tmp/roger .keystore |
No exemplo acima,
- -alias é o identificador exclusivo da sua chave.
- -keyalg é o algoritmo usado para gerar a chave. A maior parte dos exemplos que você encontrar na web irão citar o “RSA”, mas você também pode utilizar “DSA” ou “DES”.
- -keystore é um parâmetro opcional que especifica a localização do arquivo da key store. Se esse parâmetro for omitido, então a localização padrão é o seu diretório $HOME.
RSA significa Ron Rivest (também criador do algoritmo RC4), Adir Shamir e Leonard Adleman
DSA significa Digital Signature Algorithm
DES significa Data Encryption Standard
Para mais informações sobre o keytool e seus parâmetros, dê uma olhada neste artigo do Informit, por Jon Svede.
Quando executar esse programa, algumas perguntas serão feitas para você:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
Roger$ keytool -genkey - alias MyKeyAlias -keyalg RSA -keystore /Users/Roger/tmp/roger .keystore Enter keystore password: Re-enter new password: What is your first and last name? [Unknown]: localhost What is the name of your organizational unit? [Unknown]: MyDepartmentName What is the name of your organization? [Unknown]: MyCompanyName What is the name of your City or Locality? [Unknown]: Stafford What is the name of your State or Province? [Unknown]: NA What is the two-letter country code for this unit? [Unknown]: UK Is CN=localhost, OU=MyDepartmentName, O=MyCompanyName, L=Stafford, ST=UK, C=UK correct? [no]: Y Enter key password for (RETURN if same as keystore password): |
A maior parte dos campos é autoexplicativa; contudo, para os valores do primeiro e segundo nome, eu geralmente utilizo o nome da máquina – neste caso, localhost.
Atualizando a configuração do Tomcat
O segundo passo para melhorar a segurança do aplicativo é se certificar de que seu Tomcat possui um conector SSL. Para fazer isso, você precisa encontrar o arquivo de configuração server.xml do Tomcat, que normalmente se encontra no diretório “conf”. Uma vez que tiver feito isso e caso esteja utilizando o Tomcat, então será uma questão de retirar o comentário:
1
2
3
|
< Connector port = "8443" protocol = "HTTP/1.1" SSLEnabled = "true" maxThreads = "150" scheme = "https" secure = "true" clientAuth = "false" sslProtocol = "TLS" /> |
e fazer com que ele se pareça com isto:
1
|
< Connector SSLEnabled = "true" keystoreFile = "/Users/Roger/tmp/roger.keystore" keystorePass = "password" port = "8443" scheme = "https" secure = "true" sslProtocol = "TLS" /> |
Note que a senha “password” está em texto puro, o que é muito inseguro. Há formas de resolver isso, mas estas estão fora do escopo deste artigo.
Se você estiver utilizando o tcServer do Spring, vai perceber que ele já possui um conector SSL que está configurado como algo deste tipo:
1
|
<Connector SSLEnabled="true" acceptCount="100" connectionTimeout="20000" executor="tomcatThreadPool" keyAlias="tcserver" keystoreFile="${catalina.base} |
…que em todo caso é apenas uma questão de editar os vários campos incluindo keyAlias, keystoreFile e keystorePass.
Configuração do aplicativo
Se você iniciar o Tomcat e executar o seu aplicativo web, irá perceber que ele está acessível utilizando HTTPS. Por exemplo, digitar https://localhost:8443/meu-aplicativo irá funcionar, mas http://localhost:8080/meu-aplicativo também. Isso significa que você terá que fazer alguns truques no seu aplicativo para ter certeza de que ele irá responder apenas por HTTPS e há duas formas de fazer isso.
Se não estiver utilizando o Spring Security, então pode simplesmente adicionar o seguinte trecho de código ao seu web.xml antes da última tag de web-app:
1
2
3
4
5
6
7
8
9
|
< security-constraint > < web-resource-collection > < web-resource-name >my-secure-app</ web-resource-name > < url-pattern >/*</ url-pattern > </ web-resource-collection > < user-data-constraint > < transport-guarantee >CONFIDENTIAL</ transport-guarantee > </ user-data-constraint > </ security-constraint > |
Se estiver utilizando o Spring Security, então há mais alguns passos para fazer isso. Parte da configuração do Spring Security é adicionar o trecho seguinte ao arquivoweb.xml. Primeiro, você precisa acrescentar um arquivo de contexto de aplicativo Spring Security ao parâmetro contextConfigLocation context-param:
1
2
3
4
5
6
|
< context-param > < param-name >contextConfigLocation</ param-name > < param-value >/WEB-INF/spring/root-context.xml /WEB-INF/spring/appServlet/application-security.xml </ param-value > </ context-param > |
Em seguida, é preciso adicionar o filter e o filter-mapping do Spring Security:
1
2
3
4
5
6
7
8
|
< filter > < filter-name >springSecurityFilterChain</ filter-name > < filter-class >org.springframework.web.filter.DelegatingFilterProxy</ filter-class > </ filter > < filter-mapping > < filter-name >springSecurityFilterChain</ filter-name > < url-pattern >/*</ url-pattern > </ filter-mapping > |
Por último, é necessário criar (ou editar) o seu application-security.xml como exibido no exemplo bem minimalista abaixo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<? xml version = "1.0" encoding = "UTF-8" ?> < beans:beans xmlns = "http://www.springframework.org/schema/security" xmlns:beans = "http://www.springframework.org/schema/beans" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> < http auto-config = 'true' > < intercept-url pattern = "/**" requires-channel = "https" /> </ http > < authentication-manager > </ authentication-manager > </ beans:beans > |
No exemplo acima, o elemento intercept-url foi configurado para interceptar todas as URLs e forçá-las a utilizar o canal https.
Os detalhes de configuração acima talvez passem a impressão de que é mais rápido utilizar a mudança simples na configuração do web.xml, mas se você já estiver utilizando o Spring Security, então é apenas uma questão de acrescentar os atributos requires-channel à sua configuração existente.