Pergunta

Muitas vezes encontro o seguinte cenário em que preciso oferecer muitos tipos diferentes de permissões.Eu uso principalmente ASP.NET/VB.NET com SQL Server 2000.

Cenário

Quero oferecer um sistema de permissão dinâmico que possa funcionar em diferentes parâmetros.Digamos que eu queira conceder acesso a um aplicativo a um departamento ou apenas a uma pessoa específica.E finja que temos uma série de aplicações que não param de crescer.

No passado, escolhi uma das duas maneiras que conheço de fazer isso.

  1. Use uma única tabela de permissão com colunas especiais usadas para determinar um como aplicar os parâmetros.As colunas especiais neste exemplo são TypeId e Typeauxid.O SQL seria algo assim.

    SELECT COUNT(PermissionID)
    FROM application_permissions
    WHERE
    (TypeID = 1 AND TypeAuxID = @UserID) OR
    (TypeID = 2 AND TypeAuxID = @DepartmentID)
    AND ApplicationID = 1
    
  2. Use uma tabela de mapeamento para cada tipo de permissão e junte -os a todos.

    SELECT COUNT(perm.PermissionID)
    FROM application_permissions perm
    LEFT JOIN application_UserPermissions emp
    ON perm.ApplicationID = emp.ApplicationID
    LEFT JOIN application_DepartmentPermissions dept
    ON perm.ApplicationID = dept.ApplicationID
    WHERE q.SectionID=@SectionID
      AND (emp.UserID=@UserID OR dept.DeptID=@DeptID OR
     (emp.UserID IS NULL AND dept.DeptID IS NULL)) AND ApplicationID = 1
    ORDER BY q.QID ASC
    

Meus pensamentos

Espero que os exemplos façam sentido.Eu os juntei.

O primeiro exemplo requer menos trabalho, mas nenhum deles parece ser a melhor resposta.Existe uma maneira melhor de lidar com isso?

Foi útil?

Solução

Concordo com John Downey.

Pessoalmente, às vezes uso uma enumeração sinalizada de permissões.Desta forma você pode usar operações AND, OR, NOT e XOR bit a bit nos itens da enumeração.

"[Flags]
public enum Permission
{
    VIEWUSERS = 1, // 2^0 // 0000 0001
    EDITUSERS = 2, // 2^1 // 0000 0010
    VIEWPRODUCTS = 4, // 2^2 // 0000 0100
    EDITPRODUCTS = 8, // 2^3 // 0000 1000
    VIEWCLIENTS = 16, // 2^4 // 0001 0000
    EDITCLIENTS = 32, // 2^5 // 0010 0000
    DELETECLIENTS = 64, // 2^6 // 0100 0000
}"

Então, você pode combinar várias permissões usando o operador AND bit a bit.

Por exemplo, se um usuário puder visualizar e editar usuários, o resultado binário da operação será 0000 0011, que convertido em decimal será 3.
Você pode então armazenar a permissão de um usuário em uma única coluna do seu banco de dados (no nosso caso seriam 3).

Dentro da sua aplicação, você só precisa de outra operação bit a bit (OR) para verificar se um usuário tem uma permissão específica ou não.

Outras dicas

A maneira como normalmente codifico sistemas de permissão é ter 6 tabelas.

  • Usuários - isso é bastante simples, é sua tabela típica de usuários
  • Grupos - isso seria sinônimo de seus departamentos
  • Funções - esta é uma tabela com todas as permissões, geralmente incluindo também um nome legível e uma descrição
  • Users_have_Groups - esta é uma tabela muitos para muitos de quais grupos um usuário pertence
  • Users_have_Roles - outra tabela muitos para muitos de quais funções são atribuídas a um usuário individual
  • Groups_have_Roles - a tabela final muitos-para-muitos de quais funções cada grupo possui

No início de uma sessão de usuários, você executaria alguma lógica que extraísse todas as funções atribuídas a eles, seja em um diretório ou por meio de um grupo.Em seguida, você codifica essas funções como suas permissões de segurança.

Como eu disse, isso é o que normalmente faço, mas sua milhagem pode variar.

Além das soluções de John Downey e jdecuyper, também adicionei um bit "Negação explícita" no final/início do campo de bits, para que você possa executar permissões aditivas por grupo, associação de função e, em seguida, subtrair permissões com base na negação explícita entradas, assim como o NTFS funciona, em termos de permissão.

Honestamente, os recursos de associação/funções do ASP.NET funcionariam perfeitamente para o cenário que você descreveu.Escrever suas próprias tabelas/procs/classes é um ótimo exercício e você pode obter um ótimo controle sobre detalhes minuciosos, mas depois de fazer isso sozinho, concluí que é melhor usar apenas o material .NET integrado.Muito código existente é projetado para contornar isso, o que é ótimo.Escrever do zero levou cerca de 2 semanas e não foi tão robusto quanto o .NETs.Você tem que codificar muita porcaria (recuperação de senha, bloqueio automático, criptografia, funções, uma interface de permissão, toneladas de processos, etc.) e o tempo poderia ser melhor gasto em outro lugar.

Desculpe se não respondi sua pergunta, sou como o cara que diz para aprender c# quando alguém faz uma pergunta sobre vb.

Uma abordagem que usei em vários aplicativos é ter uma classe PermissionToken genérica que possui uma propriedade Value mutável.Em seguida, você consulta o aplicativo solicitado e ele informa quais PermissionTokens são necessários para usá-lo.

Por exemplo, o aplicativo Shipping pode informar que precisa de:

new PermissionToken()
{
    Target = PermissionTokenTarget.Application,
    Action = PermissionTokenAction.View,
    Value = "ShippingApp"
};

Obviamente, isso pode ser estendido para Criar, Editar, Excluir etc. e, por causa da propriedade Value personalizada, qualquer aplicativo, módulo ou widget pode definir suas próprias permissões necessárias.YMMV, mas esse sempre foi um método eficiente para mim, que descobri ser bem escalonável.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top