Piense en una Autoridad concedida como un "permiso" o un "derecho". Esos "permisos" se expresan (normalmente) como cadenas (con el getAuthority()
método). Esas cadenas le permiten identificar los permisos y dejar que sus votantes decidan si otorgan acceso a algo.
Puede otorgar diferentes GrantedAuthoritys (permisos) a los usuarios poniéndolos en el contexto de seguridad. Normalmente lo hace implementando su propio UserDetailsService que devuelve una implementación de UserDetails que devuelve las GrantedAuthorities necesarias.
Los roles (como se usan en muchos ejemplos) son solo "permisos" con una convención de nomenclatura que dice que un rol es una GrantedAuthority que comienza con el prefijo ROLE_
. No hay nada mas. Un rol es solo una Autoridad otorgada - un "permiso" - un "derecho". Verá muchos lugares en la seguridad de primavera donde el rol con su ROLE_
prefijo se maneja especialmente, por ejemplo, en RoleVoter, donde el ROLE_
prefijo se usa por defecto. Esto le permite proporcionar los nombres de los roles sin el ROLE_
prefijo. Antes de Spring Security 4, este manejo especial de "roles" no se seguía de manera muy consistente y las autoridades y los roles a menudo se trataban de la misma manera (por ejemplo,hasAuthority()
hasRole()
) Con Spring Security 4, el tratamiento de roles es más consistente y el código que trata con "roles" (como el RoleVoter
, la hasRole
expresión, etc.) siempre agrega el ROLE_
prefijo para usted. Entonces hasAuthority('ROLE_ADMIN')
significa lo mismo que hasRole('ADMIN')
porque el ROLE_
prefijo se agrega automáticamente. Consulte la guía de migración de Spring Security 3 a 4 para obtener más información.
Pero aún así: un rol es solo una autoridad con un ROLE_
prefijo especial . Entonces, en Spring security 3 @PreAuthorize("hasRole('ROLE_XYZ')")
es igual @PreAuthorize("hasAuthority('ROLE_XYZ')")
y en Spring security 4 @PreAuthorize("hasRole('XYZ')")
es igual que @PreAuthorize("hasAuthority('ROLE_XYZ')")
.
Con respecto a su caso de uso:
Los usuarios tienen roles y los roles pueden realizar ciertas operaciones.
Podría terminar en GrantedAuthorities
los roles a los que pertenece un usuario y las operaciones que puede desempeñar un rol. Los GrantedAuthorities
roles tienen el prefijo ROLE_
y las operaciones tienen el prefijo OP_
. Un ejemplo para las autoridades de operación podrían ser OP_DELETE_ACCOUNT
, OP_CREATE_USER
, OP_RUN_BATCH_JOB
etc. roles pueden ser ROLE_ADMIN
, ROLE_USER
, ROLE_OWNER
etc.
Podría terminar haciendo que sus entidades se implementen GrantedAuthority
como en este ejemplo (pseudocó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;
}
}
Los identificadores de los roles y operaciones que crea en su base de datos serían la representación de GrantedAuthority, por ejemplo ROLE_ADMIN
, OP_DELETE_ACCOUNT
etc. Cuando un usuario se autentica, asegúrese de que todas las GrantedAuthorities de todos sus roles y las operaciones correspondientes se devuelvan desde UserDetails.getAuthorities () método.
Ejemplo: El rol de administrador con id ROLE_ADMIN
tiene operaciones OP_DELETE_ACCOUNT
, OP_READ_ACCOUNT
, OP_RUN_BATCH_JOB
asignados a la misma. El rol de usuario con id ROLE_USER
tiene la operación OP_READ_ACCOUNT
.
Si un administrador registros en el contexto de seguridad resultantes tendrán las GrantedAuthorities:
ROLE_ADMIN
, OP_DELETE_ACCOUNT
, OP_READ_ACCOUNT
,OP_RUN_BATCH_JOB
Si un usuario inicia una sesión que, tendrá:
ROLE_USER
,OP_READ_ACCOUNT
UserDetailsService se encargaría de recopilar todos los roles y todas las operaciones de esos roles y ponerlos a disposición mediante el método getAuthorities () en la instancia de UserDetails devuelta.