Função versus controle de acesso baseado em permissão


45

Estou tentando entender a troca inerente entre funções e permissões quando se trata de controle de acesso (autorização).

Vamos começar com um dado: em nosso sistema, uma Permissão será uma unidade de acesso refinada (" Editar recurso X ", " Acessar a página do painel " etc.). Uma função será uma coleção de mais de 1 permissão. Um usuário pode ter 1 ou mais funções. Todos esses relacionamentos (usuários, funções, permissões) são todos armazenados em um banco de dados e podem ser alterados rapidamente e conforme necessário.

Minhas preocupações:

(1) O que há de tão "ruim" em verificar funções para controle de acesso? Quais são os benefícios obtidos pela verificação de permissões? Em outras palavras, qual é a diferença entre esses dois trechos abaixo:

if(SecurityUtils.hasRole(user)) {
    // Grant them access to a feature
}

// vs.
if(SecurityUtils.hasPermission(user)) {
    // Grant them access to a feature
}

E:

(2) Nesse cenário, que valor útil as Funções oferecem? Não poderíamos apenas atribuir mais de uma permissão aos usuários diretamente? Que valor concreto da abstração as Funções oferecem (alguém pode dar exemplos específicos)?


2
Alguns pontos: (1) um único usuário pode ter várias funções; (2) você pode procurar na ACL (listas de controle de acesso), por exemplo. convém conceder "Acessar a página do painel" a apenas um subconjunto de páginas do painel (se houver várias).
Matthieu M.

Respostas:


63

(1) O que há de tão "ruim" em verificar funções para controle de acesso? Quais são os benefícios obtidos pela verificação de permissões?

No momento da verificação, o código de chamada precisa apenas saber "o usuário X tem permissão para executar a ação Y?" .
O código de chamada não se importa e não deve estar ciente dos relacionamentos entre funções e permissões.

A camada de autorização verificará se o usuário tem essa permissão, geralmente verificando se a função do usuário tem essa permissão. Isso permite alterar a lógica de autorização sem atualizar o código de chamada.

Se você verificar diretamente a função no site de chamada, estará implicitamente criando relacionamentos de permissão de função e injetando lógica de autorização no código de chamada, violando a separação de preocupações.

Se você decidir posteriormente que a função foonão deve ter permissão baz, será necessário alterar todos os códigos que verificam se o usuário é um foo.

(2) Nesse cenário, que valor útil as Funções oferecem? Não poderíamos apenas atribuir mais de uma permissão aos usuários diretamente? Que valor concreto da abstração as Funções oferecem (alguém pode dar exemplos específicos)?

As funções representam conceitualmente uma coleção nomeada de permissões.

Digamos que você esteja adicionando um novo recurso que permite ao usuário editar determinadas configurações. Esse recurso deve estar disponível apenas para administradores.

Se você estiver armazenando permissões por usuário, terá de encontrar todos os usuários do seu banco de dados que, de alguma forma, sejam administradores (se você não estiver armazenando informações de função para os usuários, como saberia quais usuários são administradores?) E acrescente essa permissão para sua lista de permissões.

Se você usar funções, precisará anexar a permissão à Administratorfunção, que é mais fácil de executar, mais eficiente em termos de espaço e menos propensa a erros.


Uh? A camada de autenticação verificará se o usuário é quem afirma ser; a camada que verifica que as funções / dados pode tal um acesso de utilizador é a camada de autorização
SJuan76

4
Essa leitura deve ser obrigatória para todos os programadores. Excelente.
Kosta Kontos

2
Simples, conciso e direto ao ponto - supera um capítulo inteiro de um livro em algum lugar. Obrigado.
Dan Nissenbaum 4/17/17

2
Comentário para maior clareza (e me corrija se estiver errado): authorization layerProvavelmente, nada significa mais do que simplesmente ter a definição da função (ie) user->hasPermission(SOME_PERMISSION)verificar internamente primeiro as funções do usuário e depois verificar se alguma das funções inclui / exclui o dado permissão. Por exemplo, the calling codepode estar verificando se uma determinada página está visível para o usuário e chamaria user->hasPermission(VIEW_GIVEN_PAGE), e authorization layerconsiste na definição da hasPermissionfunção que verifica as funções como acima.
Dan Nissenbaum 4/17/17

1
@ DanNissenbaum Sim, parece que você acertou, pode ser tão simples quanto verificar se a função de usuário tem essa autorização. Também poderia ser mais do que isso. Por exemplo, talvez você tenha a opção de suspender temporariamente um usuário e, nesse caso, hasPermissionpode verificar usersRole.HasPermission(VIEW_GIVEN_PAGE) && !user.Suspended. O ponto é que tudo é feito em um só lugar e não no código de consumo (de chamada).
Rotem

18

Em resposta à sua primeira pergunta, o maior problema ao verificar se um usuário tem uma função e não uma permissão específica é que as permissões podem ser mantidas por várias funções. Como exemplo disso, um desenvolvedor pode ter acesso para ver o portal do desenvolvedor na intranet da empresa, que provavelmente também é uma permissão mantida por seu gerente. Se um usuário estiver tentando acessar o portal do desenvolvedor, você terá uma verificação semelhante a:

if(SecurityUtils.hasRole(developer)) {
    // Grant them access to a feature
} else if(SecurityUtils.hasRole(manager)) {
    // Grant them access to a feature
} else if...

(Uma switchdeclaração no seu idioma de escolha seria melhor, mas ainda não particularmente organizada)

Quanto mais comum ou amplamente realizada uma permissão, mais funções de usuário você precisa verificar para garantir que alguém possa acessar um determinado sistema. Isso também levaria ao problema de que toda vez que você modificar as permissões de uma função, será necessário modificar a verificação para refletir isso. Em um sistema grande, isso se tornaria muito difícil de manejar muito rapidamente.

Se você simplesmente verificar se o usuário tem a permissão que lhes permite acessar o portal do desenvolvedor, por exemplo, não importa qual a função que eles desempenham, eles terão acesso concedido.

Para responder à sua segunda pergunta, o motivo pelo qual você tem funções é que elas agem com a facilidade de modificar e distribuir "pacotes" de permissões. Se você possui um sistema com centenas de funções e milhares de permissões, a adição de um novo usuário (por exemplo, um novo gerente de RH) exigiria que você passasse e concedesse a ele todas as permissões que outros gerentes de RH possuem. Isso não seria apenas entediante, mas também propenso a erros se feito manualmente. Compare isso simplesmente adicionando a função "Gerente de RH" ao perfil de um usuário, o que concederá a eles o mesmo acesso que qualquer outro usuário com essa função.

Você pode argumentar que pode simplesmente clonar um usuário existente (se o seu sistema oferecer suporte a isso), mas, embora isso conceda ao usuário as permissões corretas para esse momento, tentar adicionar ou remover uma permissão para todos os usuários no futuro pode ser difícil. Um exemplo de cenário para isso é se, talvez no passado, a equipe de RH também estivesse encarregada da folha de pagamento, mas mais tarde a empresa se tornasse suficientemente grande para contratar pessoal especificamente para lidar com a folha de pagamento. Isso significa que o RH não precisa mais acessar o sistema de folha de pagamento, para que a permissão possa ser removida. Se você possui 10 membros diferentes de RH, precisará passar manualmente e remover a permissão correta, que introduz a possibilidade de erro do usuário. O outro problema com isso é que ele simplesmente não escala; À medida que você ganha mais e mais usuários em uma determinada função, torna muito mais difícil a modificação de uma função. Compare isso com o uso de funções, onde você precisaria modificar apenas a função abrangente em questão para remover a permissão, que seria refletida por todos os usuários que possuem essa função.


bom exemplo, obrigado!
frank
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.