Pense em uma GrantedAuthority como sendo uma "permissão" ou um "direito". Essas "permissões" são (normalmente) expressas como seqüências de caracteres (com o getAuthority()
método). Essas cadeias permitem identificar as permissões e permitir que seus eleitores decidam se concedem acesso a algo.
Você pode conceder diferentes GrantedAuthoritys (permissões) aos usuários colocando-os no contexto de segurança. Você normalmente faz isso implementando seu próprio UserDetailsService que retorna uma implementação de UserDetails que retorna as GrantedAuthorities necessárias.
Funções (como são usadas em muitos exemplos) são apenas "permissões" com uma convenção de nomenclatura que diz que uma função é uma GrantedAuthority que começa com o prefixo ROLE_
. Não há mais nada. Uma função é apenas uma Autoridade Concedida - uma "permissão" - um "direito". Você vê muitos lugares na segurança da primavera em que a função com seu ROLE_
prefixo é tratada especialmente como, por exemplo, no RoleVoter, onde o ROLE_
prefixo é usado como padrão. Isso permite que você forneça os nomes das funções sem o ROLE_
prefixo. Antes da segurança da Primavera 4, esse tratamento especial de "funções" não era seguido de maneira muito consistente e as autoridades e funções eram frequentemente tratadas da mesma maneira (como vocêhasAuthority()
hasRole()
) Com o Spring Security 4, o tratamento de funções é mais consistente e o código que lida com "funções" (como RoleVoter
a hasRole
expressão etc.) sempre adiciona o ROLE_
prefixo para você. Isso hasAuthority('ROLE_ADMIN')
significa o mesmo que hasRole('ADMIN')
porque o ROLE_
prefixo é adicionado automaticamente. Consulte o guia de migração de segurança de mola 3 a 4 para obter mais informações.
Mas ainda assim: um papel é apenas uma autoridade com um ROLE_
prefixo especial . Portanto, no Spring security 3 @PreAuthorize("hasRole('ROLE_XYZ')")
é o mesmo que @PreAuthorize("hasAuthority('ROLE_XYZ')")
e no Spring security 4 @PreAuthorize("hasRole('XYZ')")
é o mesmo que @PreAuthorize("hasAuthority('ROLE_XYZ')")
.
Em relação ao seu caso de uso:
Os usuários têm funções e as funções podem executar determinadas operações.
Você pode acabar com GrantedAuthorities
as funções às quais um usuário pertence e as operações que uma função pode executar. As GrantedAuthorities
funções para têm o prefixo ROLE_
e as operações têm o prefixo OP_
. Um exemplo para as autoridades de operação poderia ser OP_DELETE_ACCOUNT
, OP_CREATE_USER
, OP_RUN_BATCH_JOB
etc. Os papéis podem ser ROLE_ADMIN
, ROLE_USER
, ROLE_OWNER
etc.
Você pode acabar implementando suas entidades GrantedAuthority
como neste exemplo (pseudo-código):
@Entity
class Role implements GrantedAuthority {
@Id
private String id;
@ManyToMany
private final List<Operation> allowedOperations = new ArrayList<>();
@Override
public String getAuthority() {
return id;
}
public Collection<GrantedAuthority> getAllowedOperations() {
return allowedOperations;
}
}
@Entity
class User {
@Id
private String id;
@ManyToMany
private final List<Role> roles = new ArrayList<>();
public Collection<Role> getRoles() {
return roles;
}
}
@Entity
class Operation implements GrantedAuthority {
@Id
private String id;
@Override
public String getAuthority() {
return id;
}
}
Os IDs das funções e operações que você cria em seu banco de dados são a representação GrantedAuthority, por exemplo ROLE_ADMIN
, OP_DELETE_ACCOUNT
etc. Quando um usuário é autenticado, verifique se todas as GrantedAuthorities de todas as suas funções e as operações correspondentes são retornadas do UserDetails.getAuthorities () método.
Exemplo: A função admin com id ROLE_ADMIN
tem as operações OP_DELETE_ACCOUNT
, OP_READ_ACCOUNT
, OP_RUN_BATCH_JOB
atribuído a ele. A função de usuário com id ROLE_USER
possui a operação OP_READ_ACCOUNT
.
Se um administrador logs no contexto de segurança resultante terá os GrantedAuthorities:
ROLE_ADMIN
, OP_DELETE_ACCOUNT
, OP_READ_ACCOUNT
,OP_RUN_BATCH_JOB
Se um usuário fizer isso, ele vai ter:
ROLE_USER
,OP_READ_ACCOUNT
O UserDetailsService cuidaria de coletar todas as funções e todas as operações dessas funções e disponibilizá-las pelo método getAuthorities () na instância retornada de UserDetails.
hasRole('xyz')
Spring Security 4 espera que você tenha o prefixo ROLE_, enquanto quehasAuthority('xyz')
ele não espera o prefixo e avalia exatamente o que é passado. Eu usei essa solução, mas estava com problemashasRole('OP_MY_PERMISSION')
desde o prefixo ROLE_ era necessário. Em vez disso, eu deveria estar usando ohasAuthority('OP_MY_PERMISSION')
desde que não tinha o prefixo.<sec:authorize access="hasRole('ADMIN')">
é o mesmo que<sec:authorize access="hasRole('ROLE_ADMIN')">
AFAIK GrantedAuthority e as funções são as mesmas na segurança da primavera. A string getAuthority () da GrantedAuthority é a função (conforme a implementação padrão SimpleGrantedAuthority).
Para o seu caso, você pode usar Funções Hierárquicas
Não é o sol exato que você procura, mas espero que ajude
Editar : responda ao seu comentário
O papel é como uma permissão na segurança da primavera. o uso de intercept-url com hasRole fornece um controle muito refinado de qual operação é permitida para qual função / permissão.
A maneira como lidamos com nosso aplicativo é que definimos permissão (função) para cada operação (ou URL de descanso), por exemplo, view_account, delete_account, add_account etc. Em seguida, criamos perfis lógicos para cada usuário, como admin, guest_user, normal_user. Os perfis são apenas um agrupamento lógico de permissões, independente da segurança da mola. Quando um novo usuário é adicionado, um perfil é atribuído a ele (com todas as permissões permitidas). Agora, sempre que o usuário tenta executar alguma ação, a permissão / função dessa ação é verificada em relação às permissões concedidas pelo usuário.
Além disso, o RoleVoter defaultn usa o prefixo ROLE_; portanto, qualquer autoridade que comece com ROLE_ é considerada uma função, você pode alterar esse comportamento padrão usando um RolePrefix personalizado no votante da função e usando-o na segurança da primavera.
fonte
Outra maneira de entender a relação entre esses conceitos é interpretar um ROLE como um contêiner de autoridades.
As autoridades são permissões refinadas visando uma ação específica acoplada às vezes a escopo ou contexto de dados específicos. Por exemplo, Ler, Escrever, Gerenciar, pode representar vários níveis de permissões para um determinado escopo de informações.
Além disso, as autoridades são aplicadas profundamente no fluxo de processamento de uma solicitação, enquanto o ROLE é filtrado pelo filtro de solicitação antes de chegar ao Controlador. As melhores práticas prescrevem a implementação da aplicação das autoridades após o Controlador na camada de negócios.
Por outro lado, ROLES são representações granulares de um conjunto de permissões. Um ROLE_READER teria apenas autoridade de leitura ou exibição, enquanto um ROLE_EDITOR teria leitura e gravação. As funções são usadas principalmente para uma primeira triagem nos arredores do processamento de solicitações, como http. ... .antMatcher (...). hasRole (ROLE_MANAGER)
As autoridades sendo aplicadas profundamente no fluxo do processo da solicitação permitem uma aplicação mais refinada da permissão. Por exemplo, um usuário pode ter permissão de leitura e gravação para primeiro nível de um recurso, mas apenas leitura para um sub-recurso. Ter um ROLE_READER restringiria seu direito de editar o recurso de primeiro nível, pois ele precisa da permissão de gravação para editar esse recurso, mas um interceptor @PreAuthorize poderia bloquear seu tentativa de editar o sub-recurso.
Jake
fonte
Como outros já mencionaram, penso nas funções como contêineres para permissões mais granulares.
Embora eu ache que a implementação da Função de Hierarquia está sem controle fino dessas permissões granulares.
Então, criei uma biblioteca para gerenciar os relacionamentos e injetar as permissões como autoridades concedidas no contexto de segurança.
Talvez eu tenha um conjunto de permissões no aplicativo, como CREATE, READ, UPDATE, DELETE, que são associadas à função do usuário.
Ou permissões mais específicas, como READ_POST, READ_PUBLISHED_POST, CREATE_POST, PUBLISH_POST
Essas permissões são relativamente estáticas, mas o relacionamento das funções com elas pode ser dinâmico.
Exemplo -
Você pode criar APIs para gerenciar o relacionamento dessas permissões com uma função.
Não quero copiar / colar outra resposta, então aqui está o link para uma explicação mais completa sobre SO.
https://stackoverflow.com/a/60251931/1308685
Para reutilizar minha implementação, criei um repositório. Por favor sinta-se livre para contribuir!
https://github.com/savantly-net/spring-role-permissions
fonte