Onde a autorização se encaixa em uma arquitetura em camadas?


24

Normalmente, eu coloco decisões de autorização nos controladores do servidor. Esses foram os pontos de extremidade RESTful recentemente, mas acho que o mesmo vale para as arquiteturas do tipo MVC. Por uma questão de argumento, assuma que é uma autorização baseada em função. Um método protegido será anotado ou fará verificações e retornará 403s, se necessário.

Agora, considerando que a autorização é de fato uma regra comercial - "apenas administradores podem listar X", por exemplo, acho que eles devem ser empurrados para uma camada. Quando um controlador solicita que a camada de negócios execute a operação, o serviço ou a camada de negócios informa ao controlador que não está autorizado.

Essa é uma abordagem razoável? Existem desvantagens nisso?

Detesto ter um AuthorisationService que essencialmente contém um monte de regras codificadas de procedimentos estáticos para fazer isso, mas talvez faça sentido manter toda a lógica de acesso em um único local. É uma preocupação transversal que deve ser mantida em separado?

Então, eu estou perguntando se alguém fez isso e como eles conseguiram isso de uma maneira limpa ou se existem bons recursos que eu possa ler. Estou usando o Java fwiw, mas esta é uma questão independente da linguagem.

Eu verifiquei as perguntas relacionadas aqui e elas são muito finas no chão e respostas. Por exemplo: Validação e Autorização em Modelos de Domínio e Transmitindo isso através de uma Camada de Serviço para MVC

Estou lendo os documentos de segurança da primavera que apresentam bons argumentos por se tratar de uma preocupação transversal, mas estou preocupado que seja apenas o "caminho da primavera" e que gostaria de ter perspectivas mais amplas. Também vincula seu aplicativo a uma estrutura específica.


1
O status 403 está incorreto para problemas de autorização. Use 401.
gnasher729

@ gnasher729 Eu acho que é ao contrário. 401 significa que a autenticação falhou ou não é fornecida, 403 significa que você não tem direitos de acesso: stackoverflow.com/questions/3297048/…
JimmyJames

@ JimmyJames, existe outra escola de pensamento de que você deve usar apenas um deles para todas as falhas de autenticação e autorização, pois isso não permite que ferramentas automatizadas inferam a lógica de negócios com a mesma facilidade. Há alguma margem de manobra.
Berin Loritsch

1
@BerinLoritsch Desculpe, você está dizendo que a idéia é tornar mais difícil entender se é um problema de autenticação ou autorização? O RFC parece bastante claro, mas afirma que você pode usar 404 em vez de 403 se não quiser expor muitas informações. Existe uma referência que você pode fornecer para o argumento para usar um 401 em vez de 403?
JimmyJames

@JimmyJames, Sim. Esse processo de pensamento vem de profissionais de segurança, não de desenvolvedores. E também vi sua recomendação do 404 de ocultar completamente as informações para ocultar que o recurso existe.
Berin Loritsch

Respostas:


9

É uma boa prática expor apenas as opções para as quais um usuário está autorizado.

Isso força a autorização a ser uma preocupação transversal. A "Visualização" precisa saber o que um usuário pode fazer antes de criar opções e menus para exibição.

O back-end não deve confiar no front-end para tomar decisões de segurança, portanto, deve verificar a própria autorização.

Pode haver regras comerciais que efetuem a autorização dependendo dos dados, por exemplo, "Somente usuários com saldo acima de US $ 5.000 podem invocar uma transferência de moeda estrangeira" ou "Somente um usuário localizado na matriz pode visualizar essas contas". Portanto, é necessária alguma lógica de autorização dentro da lógica de negócios.

Também há autorizações técnicas a serem consideradas - quem tem permissão para visualizar os logs, quem pode fazer backup / restaurar o banco de dados etc.

Portanto, no final, todos os componentes do seu site podem ter alguns requisitos específicos de segurança e / ou autorização, na prática é quase impossível agrupar isso em uma "camada de autorização" separada.


7

Eu acho que é uma abordagem absolutamente razoável obter autorização na sua camada de Serviço. Você precisa proteger seu serviço contra atividades não autorizadas (especialmente modificações de dados). Sua camada de serviço pode residir em uma biblioteca e ser usada por diferentes camadas de apresentação (você pode ter diferentes aplicativos de interface do usuário que usam a mesma camada de serviço). E você não pode confiar no fato de que camadas específicas da apresentação executam a validação necessária. Isso é especialmente importante se você decidir posteriormente mover sua camada de Serviço para o processo separado (por exemplo, seguindo a abordagem SOA).

Agora, sobre como conseguir isso de uma "maneira limpa". Não gosto da idéia de jogar lixo na lógica de negócios com verificações de autorização; portanto, alguma implementação específica da abordagem de programação orientada a aspectos pode ajudar: pode ser decorar métodos de serviço com atributos especiais ou usar proxies dinâmicos com interceptações.

E, mais importante, preciso admitir que, em projetos muito simples, você pode viver sem validações separadas, apenas para simplificar sua vida. Mas é importante não perder o momento em que "projeto simples" começou a se tornar "projeto complexo".


7

Eu gosto de baixar as verificações de autorização o mais baixo possível! (Mas não mais!)

Você ainda pode escrever testes de autorização automatizados nas camadas "acima" disso. E algumas regras podem ser aplicáveis ​​apenas ou fazer sentido em camadas superiores, como a camada de serviço (CanView / CanSerialize?). Porém, geralmente penso que a estratégia de autorização mais segura também é a estratégia "DRY-est": mantenha a autorização o mais baixa possível, no código mais "comum" ou "compartilhado" possível (sem complicar demais as regras de autenticação).

Pense na alternativa. Se suas regras de autorização forem testadas e aplicadas apenas na camada de serviço, deixando seus objetos de domínio ruim se dobrarem às vontades de objetos de serviço mal-humorados, muitas vezes você precisará impor cada regra individual mais de uma vez, em vários objetos e vários lugares em cada objeto e em código mais complicado.

Além disso, quando sua equipe de análise contrata uma empresa de consultoria para escrever serviços de relatório usando seus objetos de domínio, você não precisa confiar nesses desenvolvedores! (Ou seja o que for. Você cria serviços ou chamadas adicionais sobre os mesmos objetos por qualquer motivo.) Você não vai querer abrir o grande livro de regras de negócios e esperar aplicá-las adequadamente novamente ; você deseja que seu domínio já os conheça e faça cumprir.


Sapato @ Se eu entendo sua preocupação - esse é o ponto. Se apenas um "administrador" tiver permissão, de acordo com as regras de negócios, para criar um Widget, a mesma regra se aplicará a todos os lugares. (Então não arriscar deixar ninguém ignorá-lo!) Se a regra não se aplica em todos os lugares, não é realmente uma regra sobre Widgetse única Widgets . . Empurre as regras para baixo o máximo possível (as regras individuais); mas, não tão longe como "regras" pode ir ... Eu sinto que não estou afirmando a distinção bem. Mas, é suposto haver distinção lá.
Svidgen

Na minha experiência, as regras de autorização geralmente fazem parte das regras de negócios. Como tal, "o mais longe possível" é frequentemente a minha camada de domínio. Porém, suspeito que o local onde suas regras "deveriam" se enquadrar é apenas uma consequência do seu domínio, da natureza das regras e da maneira como a empresa fala sobre elas.
Svidgen
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.