plugin auth grails spring-security

auth - spring security grails 2.5 6



grails rol y grupo de seguridad de primavera (3)

He configurado mi seguridad de primavera para trabajar con grupos.

Usé este scipt para crear las clases de dominio:

grails s2-quickstart com.yourapp User Role --groupClassName=RoleGroup

Supuse que un usuario puede tener muchos grupos donde un grupo puede tener muchos roles

Este es el aspecto que tiene un método generado en la clase Usuario:

Set<RoleGroup> getAuthorities() { UserRoleGroup.findAllByUser(this).collect { it.roleGroup } }

Pero ahora vi que el script también creó una clase llamada UserRole, que es la asociación entre el usuario y el rol. Entonces, ¿un usuario TAMBIÉN PUEDE tener muchos roles directamente?

Lo intenté y se guarda en la base de datos. Modifiqué el método así:

def getAuthorities() { def authorities = UserRoleGroup.findAllByUser(this).collect { it.roleGroup } authorities.addAll(UserRole.findAllByUser(this).collect { it.role }) return authorities }

Ahora, cuando creo una entrada en la base de datos en la asociación Usuario <-> Rol. No puedo iniciar sesión más. Recibo el mensaje predeterminado por seguridad de primavera diciendo básicamente que no se han encontrado credenciales.

Cuando elimino la entrada manualmente, puedo volver a iniciar sesión. Creo que esto se debe a que el método solo devuelve objetos RoleGroup.

Mis preguntas son:

a) también puedo asignar roles directamente cuando configuro Grupos

b) En caso negativo, ¿por qué el script crea esta clase?

c) Si es así, ¿cómo hago eso?


Un poco viejo, pero podría venir a la mano para cualquier otra persona que intente grupos:

En la clase de Usuario:

Set<RoleGroup> getAuthorities() { (UserRoleGroup.findAllByUser(this) as List<UserRoleGroup>)*.roleGroup as Set<RoleGroup> } Set<Role> getRoles() { (UserRoleGroup?.findAllByUser(this)?.roleGroup?.authorities.collect{it}?.flatten() ?: oldRoles) as Set<Role> } List<String> getRoleNames() { (UserRoleGroup?.findAllByUser(this)?.roleGroup?.collect{it.authorities.authority}?.flatten()?: oldRoles.authority) as List<String> } //Above will look up from userRoleGroup roleGroup.authorities = UserRole below Set<Role> getOldRoles() { (UserRole.findAllByUser(this) as List<Role>)*.role as Set<Role> }

Había estado usando Roles a pesar de que los grupos estaban habilitados y se estaban autenticando contra el viejo método oldRoles:

import grails.plugin.springsecurity.userdetails.GormUserDetailsService import grails.transaction.Transactional import org.springframework.security.authentication.UsernamePasswordAuthenticationToken import org.springframework.security.core.Authentication import org.springframework.security.core.GrantedAuthority import org.springframework.security.core.authority.SimpleGrantedAuthority import org.springframework.security.core.context.SecurityContextHolder import org.springframework.security.core.userdetails.UserDetails import org.springframework.security.core.userdetails.UsernameNotFoundException class MySpringSecurityAuthenticator extends GormUserDetailsService{ UserDetails loadUserByUsername(String username, boolean loadRoles) throws UsernameNotFoundException { return loadUserByUsername(username) } @Transactional UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { //enable login with either username or password User user = User.find { username == username || attributes.emailAddress == username || userCode == username } //if (!user) throw new UsernameNotFoundException(''User not found'', username) if (!user) throw new UsernameNotFoundException(''User not found'') return loadUserByUsername( user) } @Transactional UserDetails loadUserByUsername(User user) throws UsernameNotFoundException { if (!user) throw new UsernameNotFoundException(''User not found'') //UserDetails.withNewSession { //getAuthorities(user.oldRoles) UserDetails userDetails = new org.springframework.security.core.userdetails.User(user.username, user.password, user.enabled, !user.accountExpired, !user.passwordExpired, !user.accountLocked,getAuthoritiesFromGroup(user.authorities) ) Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()) SecurityContextHolder.getContext().setAuthentication(authentication) return userDetails //} } public static List<GrantedAuthority> getAuthoritiesFromGroup(Set<RoleGroup> roles) { List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>() roles?.each { role -> println "-- role = ${role} vs ${role.getClass()}" authorities.add(new SimpleGrantedAuthority(role.name)) } return authorities } public static List<GrantedAuthority> getAuthorities(Set<Role> roles) { List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>() roles?.each { role -> println "-- role = ${role} vs ${role.getClass()}" authorities.add(new SimpleGrantedAuthority(role.authority)) } return authorities } }

y en mi primavera / resources.groovy:

userDetailsService(MySpringSecurityAuthenticator){ grailsApplication = ref(''grailsApplication'') }

Lo que se ha estado haciendo hasta ahora era volver a los ROLES de usuario y agregarlos al manejador de autenticación a través de ... getAuthorities (user.oldRoles)

Ahora he cambiado el método anterior para leer los nombres de grupo a través de getAuthoritiesFromGroup (user.authorities)

Esto simplemente analiza los nombres de los grupos que como lado (efecto) de la versión que estoy usando también debe incluir la palabra ROLE_GROUPNAME

Entonces ahora si crean

@Transactional def grantPermission(User user, String role=''ROLE_ADMIN'', String group=''ROLE_SUPERGROUP'') { def adminRole = Role.findByAuthority(role) if (!adminRole) { adminRole = new Role(authority: role).save(flush: true) } UserRole.create user, adminRole, true def adminRoleGroup = RoleGroup.findByName(group) if (!adminRoleGroup) { adminRoleGroup = new RoleGroup(name: group).save(flush: true) } def adminRoleGroupRole = RoleGroupRole.findByRole(adminRole) if (!adminRoleGroupRole) { adminRoleGroupRole = new RoleGroupRole(role: adminRole, roleGroup: adminRoleGroup).save(flush: true) } def alreadyDone = UserRoleGroup.findByUserAndRoleGroup(user,adminRoleGroup) if (!alreadyDone) { new UserRoleGroup(user: user, roleGroup: adminRoleGroup).save(flush: true) } }

Espero autenticarme contra los nombres de grupo y no los roles de usuario, así que en resumen tuve que cambiar mi controlador a

@Secured("hasAnyRole(''ROLE_SUPERGROUP'')")

Espero que tenga sentido seguir adelante simplemente toma tiempo para entenderlo.

En este momento todavía estoy jugando y no usaría la respuesta concreta ya que estoy pirateando para decir que agreguen mis grupos como mis autoridades y si quisiera podría agregar otro gancho para ir más allá de cada uno de esos grupos y cada uno de los roles reales en él también, sin saber qué producirá, en este momento

Quiero cambiarlo a requestMaps y moverlo a db para modificarlo mucho y decidiré si debo volver atrás o usar grupos. Sé de esta manera que puedo configurar menos nombres sobre los controladores y confiar en los nombres de los grupos.

De cualquier manera está bajo el capó de todo y le da una idea clara unos años después, pero puede ser útil para otros

Actualización Así que he decidido ir con:, ,getAuthorities(user.roles)

Donde Set<Role> getRoles() { método dentro del bit de código anterior

La razón es bastante simple:

results?.each { it.user=User.get(it.id) println "-- /n${it.id}:${it.user.roles} /n${it.id}:${it.user.oldRoles}" 7:[Role(authority:ROLE_ADMIN), Role(authority:ROLE_ADMINAHHA)] 7:[Role(authority:ROLE_ADMIN)]

Como pueden ver, agregué un nuevo usuario con el rol getOldRoles I only see 1 en getRoles Obtuve 2 roles. Agregué un usuario con 2 roles.

Entonces esto analizará todas las funciones de usuario y las agregará a List<GrantedAuthority> la autenticación seguirá siendo a través de los nombres reales de ROLE generados como anteriormente.

Simplemente significa que cuando desactivo un grupo del usuario, esto debería dejar de cargar ese permiso para ese usuario.

eso es lo que el modelo debería estar haciendo


Es solo mi opinión: el script creó UserRole porque solo la clase de optimización, por ejemplo, si recibes Role de db y trataste de encontrar algún usuario, la hibernación debería haber recibido a todos los usuarios del proxy. Simplemente clase de optimización. Si desea un rol por usuario, puede configurarlo en UserRole.create () Agregar restricción y debería funcionar. Espero que me entiendas y te entendí bien. Que tengas un buen día


No creo que uno pueda esperar que asigne un Role directamente al User cuando usa Groups .

Asignar un Group a usuario y Role a Group .

Creo que la estructura de código presentada podría ser útil al "degradar" tu aplicación

para usar solo User y Roles , sin romper su conjunto actual de reglas.