Eu não teria escolhido redigir o comentário original da maneira como foi redigido, mas identifica um problema potencialmente legítimo.
Especificamente, as preocupações que justificam a separação são autenticação versus autorização .
Autenticação refere-se ao processo de logon e obtenção de uma identidade. É assim que os sistemas sabem quem você é e usados para coisas como personalização, propriedade de objetos etc.
Autorização refere-se ao que você tem permissão para fazer , e isso (geralmente) não é determinado por quem você é . Em vez disso, é determinado por algumas políticas de segurança, como funções ou permissões, que não se importam com coisas como seu nome ou endereço de email.
Esses dois podem mudar ortogonalmente um para o outro. Por exemplo, você pode alterar o modelo de autenticação adicionando provedores OpenID / OpenAuth. E você pode alterar a política de segurança adicionando uma nova função ou alterando de RBAC para ABAC.
Se tudo isso ocorrer em uma classe ou abstração, seu código de segurança, que é uma das ferramentas mais importantes para mitigação de riscos , se torna ironicamente de alto risco.
Eu trabalhei com sistemas em que autenticação e autorização eram muito fortemente acopladas. Em um sistema, havia dois bancos de dados de usuários paralelos, cada um para um tipo de "função". A pessoa ou equipe que o projetou aparentemente nunca considerou que um único usuário físico pode estar em ambas as funções, ou que pode haver certas ações comuns a várias funções ou que podem haver problemas com colisões de ID do usuário. Este é um exemplo reconhecidamente extremo, mas foi / é incrivelmente doloroso de se trabalhar.
Microsoft e Sun / Oracle (Java) se referem ao agregado de informações de autenticação e autorização como Principal de Segurança . Não é perfeito, mas funciona razoavelmente bem. No .NET, por exemplo, você possui o IPrincipal
que encapsula o primeiro IIdentity
- sendo um objeto de política (autorização) enquanto o último é uma identidade (autenticação). Você pode questionar razoavelmente a decisão de colocar um dentro do outro, mas o importante é que a maioria dos códigos que você escreve será para apenas uma das abstrações, o que significa que é fácil testar e refatorar.
Não há nada errado com um User.IsAdmin
campo ... a menos que haja também um User.Name
campo. Isso indicaria que o conceito "Usuário" não está definido corretamente e, infelizmente, esse é um erro muito comum entre os desenvolvedores que estão um pouco atrasados no que diz respeito à segurança. Normalmente, a única coisa que deve ser compartilhada por identidade e política é o ID do usuário, que, por coincidência, é exatamente como ele é implementado nos modelos de segurança Windows e * nix.
É completamente aceitável criar objetos de invólucro que encapsulem a identidade e a política. Por exemplo, isso facilitaria a criação de uma tela do painel em que você precisa exibir uma mensagem de "olá", além de vários widgets ou links que o usuário atual tem permissão para acessar. Contanto que este invólucro apenas agrupe as informações de identidade e política e não pretenda possuí-las. Em outras palavras, desde que não seja apresentado como uma raiz agregada .
Um modelo de segurança simplista sempre parece uma boa idéia quando você cria um novo aplicativo pela primeira vez, por causa do YAGNI e tudo mais, mas quase sempre acaba voltando para te morder mais tarde, porque, surpresa surpresa, novos recursos são adicionados!
Portanto, se você souber o que é melhor para você, manterá as informações de autenticação e autorização separadas. Mesmo que a "autorização" no momento seja tão simples quanto um sinalizador "IsAdmin", você ainda estará melhor se não fizer parte da mesma classe ou tabela que as informações de autenticação, de modo que se e quando sua política de segurança precisar mudança, você não precisa fazer cirurgia reconstrutiva em seus sistemas de autenticação, que já funciona bem.