Artigo no estilo Mentoring

Mentoring:Este artigo é útil em situações onde alterações nas políticas de acesso aos recursos da aplicação ocorrem frequentemente. Ele apresenta uma infraestrutura, baseada no framework Spring Security, que permite alterar as permissões de acesso dos usuários sem necessidade de codificação e, consequentemente, geração de novos releases. Ademais, apresenta também alguns dos novos recursos da versão 4 do Spring Security. Após sua leitura, o leitor será capaz de realizar o gerenciamento de acessos de seus sistemas com maior flexibilidade e agilidade.

Segurança é um requisito fundamental em grande parte das aplicações web, pois elas estão mais sujeitas a ataques, por conta de sua maior exposição. Para se ter uma ideia, mais de 1 milhão de incidentes foram reportados em 2014 ao Centro de Estudos, Resposta e Tratamento de Incidentes de Segurança no Brasil (CERT.br). Uma forma de minimizar a ocorrência desses incidentes, preservando a integridade do sistema e de suas informações, consiste em restringir o acesso a determinadas partes da aplicação a usuários autenticados, que, por sua vez, podem acessar somente funcionalidades relacionadas às suas competências.

Nesse contexto, o Spring Security é um framework destinado a proteger aplicações web, garantindo a identidade de seus usuários, por meio da funcionalidade de autenticação, e provendo controle de acesso a recursos, por meio da funcionalidade de autorização. Essas funcionalidades são embasadas por duas estruturas de dados básicas: usuário e autorização. Usuário contém os dados utilizados para validação da identidade dos usuários, como nome e senha, enquanto autorização contém os perfis de acesso, que agrupam diversas funcionalidades da aplicação. Um exemplo típico de perfil de acesso é o de “administrador”, que geralmente possui acesso a todas as funcionalidades. Nesse momento, saiba que a relação entre usuário e autorização é de “muitos para muitos”, onde cada usuário pode possuir várias autorizações e cada autorização pode pertencer a vários usuários.

As associações entre os perfis de acesso e as funcionalidades geralmente são definidas de forma estática, conforme exemplos contidos no material de referência e guias disponíveis no site do Spring Security. Essa construção cobre grande parte das situações existentes, mas torna necessária a participação de um desenvolvedor e a geração de uma nova versão da aplicação web sempre que for preciso alterar quais funcionalidades um perfil pode acessar. No entanto, infelizmente nem sempre é possível esperar uma próxima versão para o estabelecimento de uma nova política de acesso.

Diante desse cenário, o objetivo deste artigo é apresentar uma modelagem de dados alternativa mais flexível, que permita a criação e exclusão de perfis de acesso, assim como a associação e dissociação dinâmica de funcionalidades. Com isso, seremos capazes de criar aplicações, com segurança baseada em Spring Security, que suportem alterações constantes de políticas de acesso.

Spring Security 4

Utilizaremos neste artigo a versão 4 do Spring Security, lançada em março de 2015, para gerenciar a segurança de uma aplicação exemplo, que nos auxiliará na fixação dos conceitos apresentados. Essa versão apresenta como principais características a inclusão do suporte ao protocolo WebSocket, integração com o Spring Data e disponibilização de anotações para utilização em testes.

Suporte a WebSocket

A primeira nova característica do Spring Security 4 é a inclusão do suporte ao gerenciamento de autorizações aplicadas às mensagens do protocolo WebSocket (vide BOX 1), por meio da abstração Spring Messaging. Essa nova opção preenche uma lacuna de quase dois anos desde o lançamento da versão 4 do Spring Framework, em 2013, que incorporou esse protocolo.

Com isso, podemos, agora, aplicar políticas de acesso às mensagens transitadas via WebSocket, tanto por Java Configuration quanto por XML, utilizando as autorizações associadas ao usuário autenticado. A Listagem 1 apresenta um exemplo de configuração por Java Configuration, onde cada mensagem com destino iniciado em /user/ requer que o usuário se encontre autenticado. Já a Listagem 2 apresenta uma configuração por XML, onde todas as mensagens do tipo CONNECT são aceitas, todas as mensagens do tipo SUBSCRIBE são negadas e cada mensagem com destino iniciado em /user/ requer que o usuário se encontre autenticado e possua a autorização ROLE_USER.

Listagem 1. Configuração por Java Configuration.


  01 @Configuration
  02 public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
  03 
  04     protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
  05         messages.simpDestMatchers("/user/*").authenticated();
  06     }
  07 }

Listagem 2. Configuração por XML.


  01 <websocket-message-broker> 
  02   <intercept-message type="CONNECT" access="permitAll" />
  03   <intercept-message type="SUBSCRIBE" access="denyAll" />
  04   <intercept-message pattern="/user/**" access="hasRole('USER')" />
  05 </websocket-message-broker>

BOX 1. WebSocket

WebSocket é um protocolo, padronizado pela W3C e parte da especificação do HTML5, que proporciona comunicação bidirecional full-duplex entre clientes web e servidores sobre uma única conexão TCP. Essa tecnologia foi criada como uma alternativa ao método tradicional, que consiste na abertura de múltiplas conexões HTTP, o que acaba por gerar sobrecarga e aumento de latência.

Integração com Spring Data

Outra importante novidade do Spring Security 4 é a possibilidade de utilizar as informações do usuário autenticado diretamente em consultas criadas com a anotação @Query do Spring Data. Em versões anteriores seria necessário recolher essas informações na camada web e passá-las como parâmetro, mas a versão 4 permite referenciar os atributos do principal (objeto que armazena os dados do usuário autenticado) diretamente. Na Listagem 3, por exemplo, o método findInbox() recupera todas as mensagens endereçadas ao usuário autenticado acessando seu id diretamente, sem necessidade de recebê-lo como parâmetro.

Listagem 3. Consulta utilizando atributo de usuário autenticado.


  01 @Repository
  02 public interface MessageRepository extends PagingAndSortingRepository<Message,Long> {
  03     @Query("select m from Message m where m.to.id = ?#{ principal?.id }")
  04     Page<Message> findInbox(Pageable pageable);
  05 }

Suporte a testes

O Spring Security permite, por meio de anotações, restringir o acesso a métodos, exigindo que o usuário autenticado possua determinadas autorizações. Em suas versões anteriores, entretanto, não era possível verificar essas restrições durante a execução dos testes automatizados. Para sanar essa deficiência, a versão 4 passou a disponibilizar novas anotações voltadas aos testes que precisem acessar métodos que requeiram autorização, a saber:

· @WithMockUser – Possibilita a execução de um teste utilizando um usuário autenticado fictício. É possível especificar o nome do usuário e suas autorizações;

· @WithUserDetails – Possibilita a execução de um teste utilizando os dados de um usuário existente, recuperado por meio de uma chamada a um bean que implemente UserDetailsService; e

· @WithSecurityContext – Possibilita a criação de anotações que definam SecurityContext personalizados para os testes.

O Spring Security 4 também inclui integração com versões superiores à 4.1.3 do Spring MVC Test, possibilitando a realização de testes que envolvam: proteção contra CSRF (vide BOX 2); operações realizadas por usuários (fictícios ou existentes) autenticados; e autenticação de usuários.

BOX 2. Cross-Site Reference Forgery (CSRF)

CSRF é um tipo de ataque onde um usuário autenticado é levado a executar ações indesejadas em uma aplicação web. Nesse tipo de ataque, o atacante utiliza engenharia social para fazer com que a vítima acesse sites maliciosos enquanto se encontra autenticada na aplicação web alvo. Esses sites então enviam requisições falsas que utilizam as autorizações da vítima para realizar operações que beneficiam o atacante como, por exemplo, transferências de dinheiro em sites bancários.

Ataques CSRF geralmente ocorrem por meio de requisições do tipo GET ou POST, pois servidores geralmente não aceitam requisições do tipo PUT e DELETE provenientes de outros domínios, a não ser em caso de má configuração ou bugs.

Como forma de prevenção, recomenda-se o envio, em cada requisição, de um token CSRF gerado aleatoriamente pelo servidor por usuário e por sessão de usuário. O servidor deve passar então a verificar todas as requisições, rejeitando todas que apresentem um token CSRF incorreto.

Modelagem tradicional

Como citado anteriormente, o Spring Security se baseia em duas estruturas de dados: Usuário e Autorização, representadas pelas interfaces UserDetails e GrantedAuthority, respectivamente. Nas assinaturas dessas interfaces, apresentadas na Figura 1, verificamos que um usuário ...

Quer ler esse conteúdo completo? Tenha acesso completo