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.