Existem diversas maneiras de implementar segurança em nossos sistemas, seja abordando a solução na aplicação em si, utilizando um API Gateway, etc. Neste artigo, apresento uma solução baseada em usuários e módulos de um sistema escrito na linguagem java. Para o nosso contexto, este é um microsserviço BFF (backend-for-frontend) utilizando Orientação a Aspectos, em que a regra de validação para usuário e módulo é feita em outro microsserviço de permissionamento.
A AOP (Aspect Oriented Programming) permite a construção de um aspecto para alterar a execução de um código aplicando um comportamento adicional a ele. Os componentes do sistema não possuem conhecimento do aspecto, fazendo assim com que a implementação do aspecto é quem tenha conhecimento da arquitetura e dos componentes do sistema.
Para utilização de aspectos no código, é necessário ter uma boa convenção de nomes entre os desenvolvedores da equipe, pois o aspecto atua nos padrões de nomenclatura dos pacotes, classes e métodos. É importante manter o padrão escolhido para que não haja problemas de execuções indesejadas.
Para trabalharmos com aspectos, precisamos saber seus principais conceitos:
-> JoinPoint: Indica o ponto de execução do aspecto.
-> PointCut: É a expressão regular do JoinPoint.
-> Advice: É a ação de um aspecto para um determinado JoinPoint.
Exemplo da solução
O exemplo abaixo demonstra uma implementação utilizando AspectJ e SpringBoot framework.
Os módulos do sistema são representados através deste enum:
Criaremos a interface “ModuleSecurity” que possui um método para retornar qual modulo pertence à classe Controller que a implementa.
Na nossa Controller do módulo de Pessoas, a classe “PeopleController” possui os recursos do módulo “MODULE_PEOPLE”, que implementa a interface de Segurança e retorna seu respectivo enum.
Na Controller do módulo de Pagamentos, a classe “PaymentsController” possui os recursos do módulo “MODULE_PAYMENTS”, e também implementa a interface de Segurança, retornando seu respectivo enum.
Para as Controllers que não podem/precisam ter essa validação, basta que não seja feita a implementação da interface de segurança para que o aspecto não seja executado.
Agora, começaremos com a configuração do aspecto. A anotação “@Around” permite a adição do aspecto para todos os métodos das classes que estiverem no pacote “br.com.vitorbg.aop.web”, onde está nossas Controllers. Ou seja, estamos determinando um Advice a ser executado neste JoinPoint com a expressão regular representando o PointCut como parâmetro do “@Around”.
Por meio do trecho de código “joinPoint.getTarget()”, conseguimos identificar se a classe executada implementa a nossa interface de segurança. Caso positivo, significa que a Controller exige uma validação.
A identificação do usuário está no “UserContext”. A partir daí, a classe “AccessControlService” faz a validação de usuário e módulo.
A classe de Controle de Acesso faz uma requisição para o nosso microsserviço de permissionamento. Neste ponto, outro meio de validação de usuário e módulo pode ser utilizada.
O projeto de teste completo está neste repositório do GitHub.
Conclusão
Este artigo traz uma solução de segurança adotada na criação de um produto onde é utilizado um sistema de gerenciamento de usuários legado. Desta forma, o produto faz uma consulta neste sistema para verificar se o usuário que está acessando o recurso possui a permissão de visualizar determinado módulo do sistema.
A abordagem de aspecto permitiu simplificar a aplicação de segurança nas classes Controllers que representam recursos de um módulo do sistema — visto que, para toda requisição feita ao nosso BFF é necessário realizar uma chamada para o microsserviço de permissionamento e, assim, verificar a permissão de acesso ao módulo.
Gostou do conteúdo sobre orientação a aspectos na segurança da aplicação? Deixe seu comentário!