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.
hasRole('xyz')
de la primavera de Seguridad 4 espera que se tenga la ROLE_ prefijo mientras que elhasAuthority('xyz')
no espera que el prefijo y evalúa exactamente lo que se pasa en. He utilizado esta solución, pero se ejecuta en problemas con elhasRole('OP_MY_PERMISSION')
puesto la ROLE_ se necesitaba prefijo. En cambio, debería haber estado usando elhasAuthority('OP_MY_PERMISSION')
ya que no tenía el prefijo.<sec:authorize access="hasRole('ADMIN')">
es lo mismo que<sec:authorize access="hasRole('ROLE_ADMIN')">
AFAIK Granted La autoridad y los roles son los mismos en seguridad de primavera. La cadena getAuthority () de GrantedAuthority es el rol (según la implementación predeterminada SimpleGrantedAuthority).
Para su caso, puede utilizar roles jerárquicos
No es el sol exacto que buscas, pero espero que ayude
Editar : responde a tu comentario
El papel es como un permiso en la seguridad de primavera. El uso de intercept-url con hasRole proporciona un control muy detallado de qué operación está permitida para qué rol / permiso.
La forma en que manejamos nuestra aplicación es que definimos el permiso (es decir, el rol) para cada operación (o URL de reposo) para, por ejemplo, view_account, delete_account, add_account, etc. Luego creamos perfiles lógicos para cada usuario como admin, guest_user, normal_user. Los perfiles son solo agrupaciones lógicas de permisos, independientes de spring-security. Cuando se agrega un nuevo usuario, se le asigna un perfil (que tiene todos los permisos permitidos). Ahora, cuando el usuario intenta realizar alguna acción, el permiso / rol para esa acción se verifica contra las autoridades otorgadas por el usuario.
Además, el RoleVoter predeterminado usa el prefijo ROLE_, por lo que cualquier autoridad que comience con ROLE_ se considera un rol, puede cambiar este comportamiento predeterminado usando un RolePrefix personalizado en el votante de roles y usándolo en la seguridad de primavera.
fuente
Otra forma de entender la relación entre estos conceptos es interpretar un PAPEL como un contenedor de Autoridades.
Las autoridades son permisos específicos que se dirigen a una acción específica, a veces junto con un alcance o contexto de datos específicos. Por ejemplo, Leer, Escribir, Administrar, puede representar varios niveles de permisos para un alcance de información dado.
Además, las autoridades se imponen profundamente en el flujo de procesamiento de una solicitud, mientras que el PAPEL se filtra por el filtro de solicitud antes de llegar al Controlador. Las mejores prácticas prescriben la implementación de la aplicación de las autoridades más allá del controlador en la capa empresarial.
Por otro lado, los ROLES son una representación de grano grueso de un conjunto de permisos. Un ROLE_READER solo tendría autoridad de lectura o vista, mientras que un ROLE_EDITOR tendría tanto lectura como escritura. Los roles se utilizan principalmente para una primera evaluación en la periferia del procesamiento de solicitudes, como http. ... .antMatcher (...). hasRole (ROLE_MANAGER)
Las Autoridades que se aplican en profundidad en el flujo del proceso de la solicitud permiten una aplicación más precisa del permiso. Por ejemplo, un usuario puede tener permiso de lectura y escritura para primer nivel de un recurso, pero solo lectura para un subrecurso. Tener un ROLE_READER restringiría su derecho a editar el recurso de primer nivel, ya que necesita el permiso de escritura para editar este recurso, pero un interceptor @PreAuthorize podría bloquear su tentativa de editar el sub-recurso.
Jake
fuente
Como otros han mencionado, pienso en los roles como contenedores para permisos más granulares.
Aunque descubrí que la implementación del rol de jerarquía carece de un control preciso de estos permisos granulares.
Así que creé una biblioteca para administrar las relaciones e inyectar los permisos como autoridades otorgadas en el contexto de seguridad.
Es posible que tenga un conjunto de permisos en la aplicación, algo como CREAR, LEER, ACTUALIZAR, ELIMINAR, que luego se asocian con el Rol del usuario.
O permisos más específicos como READ_POST, READ_PUBLISHED_POST, CREATE_POST, PUBLISH_POST
Estos permisos son relativamente estáticos, pero la relación de roles con ellos puede ser dinámica.
Ejemplo
Puede crear API para administrar la relación de estos permisos con un rol.
No quiero copiar / pegar otra respuesta, así que aquí está el enlace a una explicación más completa sobre SO.
https://stackoverflow.com/a/60251931/1308685
Para reutilizar mi implementación, creé un repositorio. ¡Por favor siéntase libre de contribuir!
https://github.com/savantly-net/spring-role-permissions
fuente