1 de junio de 2009

Haciendo un login en grails

En esta ocación vamos a ver como hacer un login para nuestra aplicación web, verán lo facil que es, esto se puede hacer en unos pocos minutos.


Ya tenemos creada nuestra aplicacion llamanda BookStore, nos situamos en el directorio raiz de nuestra aplicación y instalaremos acegi, es un plugin que maneja la seguridad en una aplicacion grails. Si es que desean mas información aqui esta la pagina web del plugin acegi.

Ponemos lo sgte por consola:
[sourcecode language='java']
grails install-plugin acegi
[/sourcecode]

Seguidamente vamos a crear nuestras clases dominio que vamos a necesitar para nuestro login.
[sourcecode language='java']
grails create-auth-domains Usuario Rol Requestmap
[/sourcecode]

Entonces queremos crear Usuarios y manejar roles por Usuario... ponemos en consola lo sgte:
[sourcecode language='java']
grails generate-manager
[/sourcecode]

Este comando proporciona al usuario la posibilidad de registrarse y crear su nombre de usuario y contraseña.
[sourcecode language='java']
# grails generate-registration
[/sourcecode]

Bien ya esta... tenemos a nuestra aplicacion con login, roles y usuarios.
Fijense que simple que es, solo con cuatro script tenemos todo esto y con el soporte que nos da acegi (de springframework).

Pero no quiero quedarme alli, vamos a crear un controller para que prueben el login.

[sourcecode language='java']
grails create-controller Seguridad
[/sourcecode]

Lo modificamos para que simplemente muestre un mensaje:
[sourcecode language='java']
class SecureController {
def index = {
render 'Bienvenido a un sitio restringido'
}
}
[/sourcecode]

Recuerden que todavia no hemos creado ningun usuario o rol asi es que corramos nuestra aplicacion y comprobamos que todo esta en orden

[sourcecode language='java']
grails run-app
[/sourcecode]

http://localhost:8080/Bookstore

Para este post he optado por trabajar con anotaciones, asi es que le diremos a grails que queremos trabajar con anotaciones, y modificaremos el sgte archivo:
BookStore/grails-app/conf/SecurityConfig.groovy:
[sourcecode language='java']
security {

// see DefaultSecurityConfig.groovy for all settable/overridable properties
active = true
loginUserDomainClass = "Usuario" authorityDomainClass = "Rol"
useRequestMapDomainClass = false
useControllerAnnotations = true
}
[/sourcecode]

ya que estamos trabajando con anotaciones, borraremos las clases dominio, el controller y la vista de Requestmap:
BookStore/grails-app/domain/Requestmap.groovy
BookStore/grails-app/controllers/RequestmapController.groovy
BookStore/grails-app/views/requestmap/*)

Ahora vamos a crear un Rol, y luego creamos un usuario.

supongamos que creamos un Rol "ROLE_ADMIN"
y un usuario "Administrador"

Ahora añadiremos nuestro controller Seguridad la anotacion para que solamente pueda el rol Administrador:
[sourcecode language='java']
import org.codehaus.groovy.grails.plugins.springsecurity.Secured
class SecureController {
@Secured(['ROLE_ADMIN'])
def index = {
render 'Bienvenido a un sitio restringido'
}
}
[/sourcecode]

Bien ahora haremos que nuestro controller "Seguridad" sea la pagina de inicio, para ello vamos a modificar el sgte archivo: grails-app/conf/UrlMappings.groovy

[sourcecode language='java']
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?"{
constraints {
// apply constraints here
}
}
"/"(controller:"seguridad")
"500"(view:'/error')
}
}
[/sourcecode]

Eso es todo...

PD: Pongo a disposición el codigo fuente de este ejemplo
SecurityApp

20 comentarios:

KattyBlackyard dijo...

Great post! I'll subscribe right now wth my feedreader software!

Pupskievua dijo...

Here I am, Looking for a charming Kiev female companion to make your stay unforgettable in Kiev?. Kiev escort,high class independent escort. Young Kiev lady will be able to entertain you in her Kiev apartment in the center or visit you anywhere in Kiev. Vozmi me.

idecasso dijo...

Interesante... no habia podido entender bien como usar Acegi con Grails... y estaba haciendo eso a mano... tendre que probar a usarlo... tal vez me quite esta parte que esta haciendoseme engorrosa y me tenia preocupado :D

Giovanni dijo...

Muy buen artículo felicidades...

Fijate que he tenido problemas en implementarlo ya que me da un error de importación en import org.codehaus.groovy.grails.plugins.springsecurity.Secured

Dilcupa lo atrevido que soy, pero no sería mucha molestia de poner un ejemplo completo que involucre la parte de autenticación y luego que me cargue la pagina principal con su menú.

Muchas gracias de antemano y suerte.

Edwin Farfan dijo...

Hola Giovaani, gracias por tu comentario.

Respecto a tu inquietud, fijate si es que está instalando correctamente el plugin de acegi, particularmente a mi no me ha salido ese error que mencionas.

He puesto a disposicion el código de la aplicación de ejemplo para que te guies(esta al final).

Recuerda que debes de crear tus Roles(crea por lo menos 2 roles), y despues tu usuario, ademas cambiar la configuracion del datasource (BookStore/grails-app/conf/datasource.groovy), para que trabajes con una BD y no trabajes con HSQL.

Ahora para que cargue tu pagina principal lo puedes manejar en el controller. por Ejem:
class SecureController {
@Secured(['ROLE_ADMIN'])
def index = {
//render 'Bienvenido a un sitio restringido'
redirect (controller:'paginaPrincipal', action:'menu')
}
}

TE EN CUENTA, que estoy trabajando con anotaciones, esto puede que no estes queriendo utilizar, si es que quieres desactivar las anotaciones basta con ir al archivo (BookStore/grails-app/conf/SecurityConfig.groovy) y comentar lo sgte:
security {
active = true
loginUserDomainClass = "Usuario"
authorityDomainClass = "Rol"
requestMapClass = "RequestMap" //AGREGA ESTO
// useRequestMapDomainClass = false
// useControllerAnnotations = true
}

ademas en el controller debes de comentar la anotacion "@Secured('ROLE_ADMIN')".
El RequestMap te servirá para delimitar a que paginas quieres que entre un ROL determinado.
Ejm:
en la aplicación entra al RequestMapController, crea uno nuevo y pones:
URL Pattern: /seguridad/**
ROL: ROLE_ADMIN

Con esto estas diciendo que en la pagina '/seguridad' solo tiene permiso el administrador.

Si despues de estas explicaciones todavia es complicado, me puedes escribir un correo en privado para ir orientandote.
Saludos.

Jose dijo...

Hola, antes de nada muy bueno el tutorial, pero lo he seguido paso a paso, y me da un problema.
Nota: no uso anotaciones, porque no me las reconocia.
Cuando intento logearme me sale el siguiente error:

No such property: authorities for class: beans.Usuario

¿Tienes alguna idea de por qué? Gracias de antemano

Edwin Farfan dijo...

Primero fijate si es que te sale algún error en el momento que ejecutas alguno de estos scipts:
grails create-auth-domains Usuario Rol Requestmap
grails generate-manager.
grails generate-registration

Debe salirte en cada uno de ellos un mensaje de que todo anda bien, en caso de que salga algo extraño lo comentas para tratar de darle solución.

Ya que no estas trabajando con annotaciones, debes de especificar las paginas que quieres que esten con la seguridad con el RequestMap que como mencioné, te servirá para delimitar a que paginas quieres que acceda un 'ROL' determinado.
Ejm:
entra a la aplicación click en RequestMapController, crea uno nuevo y digitas en:
URL Pattern: /seguridad/**
ROL: ROLE_ADMIN

FIJATE bien si es que el usuario tiene el rol correspondiente (en este caso ROLE_ADMIN).

Saludos

Jose dijo...

Muchas gracias, he ejecutado otra vez los script y no me ha dado error, pero creo que ya he encontrado el problema, aunque no le motivo, y es que no me asigna al usuario los Roles, y por eso despues no encuentra la propiedad authorities.

He hecho pruebas con el RequestMapController y se como funciona, ahora voy a ver si arreglo el error y pruebo con las anotaciones que nunca he trabajado con ellas, y no se que me hace falta, lo he intentado y me da un error
"unable to resolve class Secured"
supongo que me faltara algun jar.

Gracias de nuevo por contestar tan rapido

Jose dijo...

Problema resuelto, como nunca sigo los tutoriales al pie de la letra, siempre me pasan cosas de estas.
Me creaba un rol llamado "ADMIN" y no me lo asignaba al usuario porque el rol se tiene que llamar "ROLE_lo-que-sea".

Ricardo dijo...

Hola Edwin.

Segui tus pasos al pie de la letra pero cuando carga la aplicacion me sale un error

Error 500: Cannot invoke method list() on null object
Servlet: default
URI: /DKApp/
Exception Message: Cannot invoke method list() on null object
Caused by: Cannot invoke method list() on null object
Class: GrailsAuthenticationProcessingFilter
At Line: [56]

Nose realmente a que pueda suceder. Estoy viendo el resto de codigo pero no encuentro la solucion.

Gracias de antemano

Ricardo dijo...

Ya encontre el problema (bueno casi). He estado probando la creacion usando Netbeans y no me dejaba. Lo he creado todo desde pura consola y recien funciona -.-

Una pregunta... cuando he levantado la app me ha mandado a la pantalla de home y no al de login (aun con el cambio de "/"(controller:"seguridad") en el urlmapping). Alguna posible causa?

Ricardo dijo...

Una ultima pregunta.. no deberia salirme el mensaje de Bienvenido a un sitio restringido ya que estoy definiendo que se llame al controller seguridad y no a login ?

Edwin Farfan dijo...

Hola Ricardo.

Sorry por la demora en contestar.

Tu primera inquietud creo que ya la resolviste, con respecto a la segunda pregunta el cambio en el urlmapping,se debe definir un solo "/" (home) para la aplicacion, seguramente debe de estar definido otro home, o si no es eso puedes hacer un clean a tu aplicación y puedes probrarlo de nuevo.
La ultima pregunta es fácil de resolver, mira, cuando tu dices que llamas al controller de seguridad, en realidad si lo estas haciendo pero ten en cuenta que a ese controller le estas inyectando seguridad (ya sea por anotaciones o por RequestMap), quiere decir que debes de tener el permiso necesario(si es que no estas logeado te pedirá que lo hagas)
Listo, espero que te haya servido... saludos

Ricardo dijo...

Gracias Edwin.. si ya entendi del todo la relacion de roles y usuarios. Ahora una pregunta off-topic pero tambien de Grails : Cuando quiero levantar el WAR generado en el ambiente de produccion me sale el siguiente error :

SEVERE: Error listenerStart

.. y es lo unico que me bota el log ya que no veo nada en los logs del tomcat. Por ahi he visto que puede ser por la configuracion del Datasource como tambien librerias repetidas. Nose si a ti te salio alguna vez este tipo de error.

Gracias de antemano doc ;)

Oriereome dijo...

?????????? ? ?????..

agares dijo...

muchas gracias, me ha sido muy util, recien empiezo a usar groovy y grails, pero me esta gustando mas que django :)

lagioriubmarm dijo...

??????? ??????????

????? ??? ???? dijo...

?????...


variant4
|

EdWall dijo...

Wola, una cuestión. Cuando instalo el plugin de ACEGI en mi aplicación, debe aparecerme el archivo SecurityConfig.groovy?? Es que no aparece, no se si tengo que copiarlo del plugin y pegarlo en la carpeta o que, porque al ejecutar tanto el:
-grails generate-manager
-grails generate-registration, me muestra lo siguiente:

Warning, target causing name overwriting of name default
Error executing script GenerateRegistration: java.io.FileNotFoundException: C:\Projects\bookstore\grails-app\conf\SecurityConfig.groovy

Edwin Farfan dijo...

Hola Edwall

Sí debes de tener el archivo SecurityConfig.groovy.

seguramente haz obviado algún paso anterior o no se ha instalado correctamente el plugin acegi en tu aplicacion.