Casbin
Repositório oficial: casbin/casbin: An authorization library that supports access control models like ACL, RBAC, ABAC in Golang (github.com)
Documentação oficial: Visão Geral | Casbin
TIP
Este artigo é apenas uma introdução ao Casbin. Para um entendimento mais aprofundado, visite o site oficial.
Introdução
Em um sistema, os desenvolvedores backend precisam gerenciar permissões para APIs, o que requer muito trabalho. Se cada projeto precisar implementar seu próprio sistema de permissões do zero, será uma grande perda de tempo. Grandes empresas com mais recursos tendem a desenvolver seus próprios frameworks de permissão, mas a maioria das pequenas e médias empresas não pode arcar com esses custos de desenvolvimento. Portanto, frameworks de permissão de código aberto se tornam a escolha preferida. Casbin é uma biblioteca de controle de acesso eficiente e de código aberto, desenvolvida em Go, e também suporta outras linguagens principais.
É importante notar que o Casbin é apenas um framework de controle de acesso, responsável apenas pelo controle de acesso. A lógica de autenticação não é de responsabilidade do Casbin; ele apenas armazena o mapeamento entre usuários e papéis. Suporta os seguintes modelos de controle de acesso:
- ACL (Access Control List, Lista de Controle de Acesso)
- ACL com superusuários
- ACL sem usuários: Especialmente útil para sistemas sem autenticação ou login de usuário.
- ACL sem recursos: Alguns cenários podem visar apenas tipos de recursos, em vez de recursos individuais, como permissões
write-article,read-log, etc. Não controla o acesso a artigos ou logs específicos. - RBAC (Role-Based Access Control, Controle de Acesso Baseado em Papéis)
- RBAC com papéis de recursos: Usuários e recursos podem ter papéis (ou grupos).
- RBAC com domínios/locatários: Usuários podem ter diferentes conjuntos de papéis para diferentes domínios/locatários.
- ABAC (Attribute-Based Access Control, Controle de Acesso Baseado em Atributos): Suporta sintaxe como
resource.Ownerpara obter atributos de elementos. - RESTful: Suporta caminhos como
/res/*,/res/:ide métodos HTTP comoGET,POST,PUT,DELETE. - Prioridade de negação: Suporta autorizações de permitir e negar, onde negar tem prioridade sobre permitir.
- Prioridade: As regras de política são priorizadas em ordem, semelhante às regras de firewall.
Como Funciona
No Casbin, os modelos de controle de acesso são abstraídos em arquivos de configuração baseados em PERM, onde PERM significa Policy (Política), Effect (Efeito), Request (Requisição), Matcher (Correspondência). Ao modificar o mecanismo de autorização em um projeto, basta alterar o arquivo de configuração. Um arquivo de modelo normal tem o seguinte conteúdo:
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.actEste é um modelo de controle de acesso ACL muito simples.
Política
No arquivo de configuração, a definição de política é:
[policy_definition]
p = sub, obj, actp refere-se a policy e não pode ser substituído por outros caracteres. sub refere-se a subject (sujeito da política), obj refere-se a object (objeto da política), act refere-se a action (ação).
p = sub, obj, actTambém pode haver um quarto campo eft, que se omitido, o padrão é allow.
p = sub, obj, act, eftEsta linha define apenas como a política deve ser escrita, não é a definição de política em si. Abaixo está um exemplo de política concreta:
p, jojo, cake, eatp representa que esta é uma definição de regra de política, jojo é o sujeito da política, cake é o objeto da política, eat é a ação. O significado completo é que o sujeito jojo pode executar a ação eat no objeto cake. Regras de política específicas não aparecem no arquivo de modelo; haverá um arquivo de política ou banco de dados dedicado para armazenar as políticas.
Requisição
No arquivo de configuração, a definição de requisição é:
[request_definition]
r = sub, obj, actr refere-se a request e não pode ser substituído por outros caracteres. sub refere-se a subject (sujeito da requisição), obj refere-se a object (objeto da requisição), act refere-se a action (ação da requisição). Geralmente, a definição de requisição e a definição de política têm os mesmos nomes de campos. A parte da requisição não é de responsabilidade do Casbin; é decidida pelo desenvolvedor o que é o sujeito da requisição e o que é o objeto da requisição. O Casbin apenas precisa realizar o controle de acesso com base nos campos passados.
Correspondência
No arquivo de configuração, a definição de correspondência é:
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.actm refere-se a matcher e não pode ser substituído por outros caracteres. O que segue é a regra de correspondência correspondente. A expressão acima é uma expressão booleana simples que significa que se todos os campos da requisição corresponderem exatamente aos campos da regra de política, há correspondência. Claro, também pode ser um curinga ou uma expressão regular mais poderosa.
Além disso, o matcher suporta a sintaxe in, por exemplo:
[matchers]
m = r.sub in ("root","admin")Ou também:
[matchers]
m = r.sub.Name in (r.obj.Admins)e.Enforce(Sub{Name: "alice"}, Obj{Name: "a book", Admins: []interface{}{"alice", "bob"}})Ao realizar a correspondência, o Casbin não realiza verificação de tipo, mas trata os valores como interface e verifica igualdade com ==.
Efeito
A definição de efeito faz julgamentos lógicos adicionais sobre os resultados da correspondência. No arquivo de configuração, a definição de efeito é:
[policy_effect]
e = some(where (p.eft == allow))e refere-se a effect e não pode ser substituído por outros caracteres. O quantificador some verifica se existe pelo menos uma regra de política que satisfaz o correspondedor. O quantificador any verifica se todas as regras de política satisfazem o correspondedor.
some(where (p.eft == allow))Esta regra significa que se houver um resultado allow nos resultados da correspondência, o resultado final será allow.
e = !some(where (p.eft == deny))Esta regra significa que se não houver resultados deny nos resultados da correspondência, o resultado final será allow.
e = some(where (p.eft == allow)) && !some(where (p.eft == deny))Esta regra significa que nos resultados da correspondência, se houver um resultado allow e nenhum resultado deny, o resultado final será allow.
Embora o Casbin tenha projetado essa gramática para efeitos de política, a execução atual usa apenas efeitos de política codificados. Eles não consideram essa flexibilidade muito necessária. Até agora, você deve usar os efeitos de política integrados e não pode personalizar. Os efeitos de política integrados suportados são os seguintes:
| Definição de Policy effect | Significado | Exemplo |
|---|---|---|
| some(where (p.eft == allow)) | allow-override | ACL, RBAC, etc. |
| !some(where (p.eft == deny)) | deny-override | Deny-override |
| some(where (p.eft == allow)) && !some(where (p.eft == deny)) | allow-and-deny | Allow-and-deny |
| priority(p.eft) || deny | priority | Priority |
| subjectPriority(p.eft) | Prioridade baseada em papéis | Subject Priority |
TIP
As quatro definições acima podem ser definidas múltiplas vezes, a sintaxe é
type+number, por exemplor2,p2,e2,m2.Arquivos de modelo podem ter comentários, usando o símbolo
#para comentários.
Exemplo
Abaixo está um exemplo que demonstra o processo de trabalho do arquivo de modelo. Primeiro, defina um arquivo de modelo ACL simples da seguinte forma:
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.actArquivo de política:
p, alice, data1, read
p, bob, data2, writeO processo de abstrair sujeito, objeto e ação é determinado pela lógica de negócios, que não é importante aqui, então será omitido. Abaixo está a maneira mais simples de mostrar as requisições passadas:
alice, data1, read
bob, data1, read
alice, data2, write
bob, data2, writeO arquivo de política define que alice tem permissão para realizar a operação read em data1, e bob tem permissão para realizar a operação write em data2. Nas requisições passadas:
alice, data1, readsignifica que alice deseja realizar a operação read em data1,
bob, data1, readsignifica que bob deseja realizar a operação read em data1, e o mesmo para os demais. O resultado final é:
true
false
false
trueEste é um exemplo ACL muito simples. O site oficial do Casbin permite editar e testar exemplos online. Vá para Casbin editor para testar.
RBAC
RBAC (Role-Based Access Control), Controle de Acesso Baseado em Papéis. Em comparação com o modelo ACL, há um [role_definition] adicional. Abaixo está um modelo RBAC simples:
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.actA definição de papéis é a seguinte:
[role_definition]
g = _, _g refere-se a group e não pode ser substituído por outros caracteres. Suporta a criação de múltiplos usando type+number. _ é um placeholder que indica quantos parâmetros existem. Geralmente, no Policy, g geralmente está no seguinte formato:
g, alice, data2_admin
g, mike, data1_admin
g, data1_admin data2_adminalice refere-se ao sujeito, data2_admin refere-se ao papel. Estritamente falando, o Casbin trata ambos como strings; como interpretar seu significado e uso depende do desenvolvedor.
g, alice, data2_adminsignifica que alice tem o papel data2_admin
g, mike, data1_adminsignifica que mike tem o papel data1_admin
g, data1_admin data2_adminsignifica que o papel data1_admin tem o papel data2_admin, esta é a relação de herança entre papéis.
Modelo de Papéis de Recursos
O modelo de papéis de recursos adiciona um g2 como definição de papel de recurso. A definição do modelo é a seguinte:
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
g2 = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && g2(r.obj, p.obj) && r.act == p.actExemplo de definição de Policy:
p, alice, data1, read
p, bob, data2, write
p, data_group_admin, data_group, write
g, alice, data_group_admin
g2, data1, data_group
g2, data2, data_groupg2 define o grupo de papéis de recursos, atribuindo recursos a diferentes papéis, e também define as relações entre papéis de usuários e papéis de recursos.
p, data_group_admin, data_group, writeEsta política define que um usuário com o papel data_group_admin pode realizar operações de escrita em recursos com o papel data_group.
Modelo de Domínio Multi-locatário
[request_definition]
r = sub, dom, obj, act
[policy_definition]
p = sub, dom, obj, act
[role_definition]
g = _, _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub, r.dom) && r.dom == p.dom && r.obj == p.obj && r.act == p.actO modelo de domínio multi-locatário adiciona o campo dom em comparação com o modelo RBAC tradicional, usado para indicar o domínio ao qual o sujeito pertence. Exemplo de Policy:
p, admin, domain1, data1, read
p, admin, domain1, data1, write
p, admin, domain2, data2, read
p, admin, domain2, data2, write
g, alice, admin, domain1
g, bob, admin, domain2Por exemplo:
p, admin, domain1, data1, readdefine que o sujeito admin pertencente ao domínio domain1 tem permissão para realizar a operação read em data1
g, alice, admin, domain1define que alice pertence ao domain1 e tem o papel admin
