Il y a 13 ans -
Temps de lecture 7 minutes
Grails Spring Security Plugin, la sécurité facile
Le monde Grails a le vent en poupe ces temps-ci. Bien avant le printemps on peut voir fleurir des dizaines de tutoriaux sur le net pour prendre l’outil en main et créer sa première application. Mais un simple « Getting started » ne suffit pas toujours à bien prendre la mesure de la puissance de Grails.
Je vous propose donc un petit tutoriel pour mettre en place une gestion des utilisateurs, avec gestion des rôles, filtres URL/Rôles, formulaire de souscription de compte. Pour cela, nous allons nous appuyer sur le Spring Security Plugin de Grails. C’est une étape incontournable de la création d’application, et nous allons pouvoir constater à quel point l’utilisation de Grails booste la productivité.
Béni soit le scaffolding
Commençons par créer l’application BookStore
qui nous servira de base, ainsi qu’une classe de domaine Book
.
grails create-app BookStore cd BookStore grail create-domain-class fr.xebia.bookstore.common.Book
Apportons quelques modifications à notre classe pour qu’elle soit un peu plus parlante dans la suite des exemples :
grails-app/domain/fr/xebia/bookstore/common/Book.groovy
package fr.xebia.bookstore.common class Book { String titre String auteur Date premierePublication static constraints = { titre(nullable:false) auteur(nullable:false) } }
Maintenant nous générons le CRUD autour de notre classe Book
.
grails generate-all fr.xebia.bookstore.common.Book
Installation du plugin Spring Security. Pas de panique, acegi
est toujours le nom du plugin, c’est un héritage de l’histoire
grails install-plugin acegi
Creation des classes de domaines pour la gestion de la sécurité, Utilisateur, roles et mapping de security et génération des managers associés
grails create-auth-domains fr.xebia.bookstore.security.User fr.xebia.bookstore.security.Role fr.xebia.bookstore.security.RequestMap grails generate-manager
Maintenant nous générons les composants nécessaires à la souscription d’un compte par un internaute.
grails generate-registration
A ce stade, nous disposons des contrôleurs suivants (et des vues qui vont avec) :
- CaptchaController : permet de générer des images captcha pour éviter que des robots ne viennent créer des comptes utilisateurs
- fr.xebia.bookstore.common.BookController : CRUD de gestion de la classe
Book
- LoginController : Contrôleur de connexion
- LogoutController : Contrôleur de déconnexion
- RegisterController : Contrôleur d’enregistrement d’un compte utilisateur par un internaute
- RequestMapController : CRUD de gestion des règles de sécurité
- RoleController : CRUD de gestion des rôles
- UserController : CRUD de gestion des utilisateurs, destiné à notre espace d’administration
On peut déjà démarrer l’application avec un grails run-app
et voir ce que ça donne :

Configuration et sécurisation
Cela fait déjà beaucoup de matières à exploiter en un temps relativement court. Mais en l’état c’est encore un peu brut de fonderie pour ressembler à une vraie application. Nous allons donc faire un peu de configuration et de rangement autour de tout ce code parachuté par Grails. Pour atteindre notre objectif, nous allons maintenant procéder à la sécurisation des écrans de :
- CRUD complet des utilisateurs
- CRUD complet des rôles
- CRUD complet des mappings de sécurité
- Création de
Book
Tout est déjà en place pour cela grâce au code que nous avons généré. Commençons par utiliser le RoleController
pour créer un rôle utilisateur et un rôle administrateur :

Maintenant que nous avons des rôles, il faut créer un compte utilisateur avec le rôle ROLE_ADMIN pour éviter de se retrouver bloqué quand on posera les mappings de sécurité. Cette fois, c’est du coté des écrans du UserController
que ça se passe :

Et pour finir, on pose des mappings de sécurité sur les URL qui nous intéressent, avec la liste des rôles autorisés à accéder. Pour cela, nous utilisons le RequestMapController
:

Et voilà ! Notre application répond déjà mieux à nos attentes en terme de sécurité :
- tout le monde peut voir la liste des
Book
présents en base. - seuls les utilisateur ayant le rôle ROLE_USER ou ROLE_ADMIN peuvent insérer de nouveaux
Book
- seuls les utilisateur ayant le rôle ROLE_ADMIN peuvent créer des utilisateurs, des rôles et modifier les règles de sécurité
Si un utilisateur non authentifié tente d’accéder à une URL protégée, il sera automatiquement redirigé vers un écran de login avant d’accéder à la page désirée.
Adaptations de confort
Par défaut, une application Grails utilise HSQLDB et démarre avec une base vierge à chaque lancement. Nous allons donc changer cela pour intégrer directement à chaque démarrage les rôles, mappings de sécurité et un compte administrateur :
grails-app/conf/BootStrap.groovy
import fr.xebia.bookstore.security.User import fr.xebia.bookstore.security.Role import fr.xebia.bookstore.security.RequestMap class BootStrap { def authenticateService def init = { servletContext -> def roleAdmin = new Role(authority: 'ROLE_ADMIN', description: 'Administrateur').save() def roleUser = new Role(authority: 'ROLE_USER', description: 'Utilisateur').save() def userAdmin = new User(username: 'admin', userRealName: 'ATTAN Charles', passwd: authenticateService.encodePassword('admin'), enabled: true, email: 'admin@bookstore.fr') userAdmin.addToAuthorities(roleAdmin) userAdmin.save() def protectBookCreation = new RequestMap(url: '/book/create*', configAttribute: 'ROLE_ADMIN,ROLE_USER').save() def protectUserManaging = new RequestMap(url: '/user/*', configAttribute: 'ROLE_ADMIN').save() def protectRoleManaging = new RequestMap(url: '/role/*', configAttribute: 'ROLE_ADMIN').save() def protectSecurityMappingManaging = new RequestMap(url: '/requestMap/*', configAttribute: 'ROLE_ADMIN').save() } def destroy = { } }
Voilà, au prochain démarrage nous retrouverons toutes nos chères données directement en base. Ensuite, nous pouvons nous attaquer à l’enregistrement des internautes en tant qu’utilisateur standard. Par défaut, le formulaire lié au RegisterController
crée des utilisateurs sans rôle, ce qui ne nous convient pas du tout. De plus, comme il serait agréable pour les nouveaux utilisateurs de recevoir un mail de confirmation de leur inscription, on va le mettre en place dans la foulée :
grails-app/conf/SecurityConfig.groovy
security { active = true loginUserDomainClass = "fr.xebia.bookstore.security.User" authorityDomainClass = "fr.xebia.bookstore.security.Role" requestMapClass = "fr.xebia.bookstore.security.RequestMap" defaultRole = 'ROLE_USER' // Role par defaut des nouveaux utilisateurs useMail = true // specifie d'envoyer un mail à l'enregistrement d'un compte mailHost = 'localhost' // serveur d'envoi de mails mailProtocol = 'smtp' // nom du protocole JavaMail mailFrom = 'no.reply@bookstore.fr' // adresse de l'envoyeur du mail mailPort = 25 // port de connexion au serveur de mail }
Avec ces modifications, tous les internautes qui créeront des comptes par le formulaire obtiendrons le rôle ROLE_USER et recevront un mail comme ceci :

Si vous souhaitez adapter un peu le format du mail, le code associé est situé vers la ligne 170 du code de RegisterController
:
extrait de grails-app/controllers/RegisterController.groovy
[...] if (config.security.useMail) { String emailContent = """You have signed up for an account at: ${request.scheme}://${request.serverName}:${request.serverPort}${request.contextPath} Here are the details of your account: ------------------------------------- LoginName: ${person.username} Email: ${person.email} Full Name: ${person.userRealName} Password: ${params.passwd} """ def email = [ to: [person.email], // 'to' expects a List, NOT a single email address subject: "[${request.contextPath}] Account Signed Up", text: emailContent // 'text' is the email body ] emailerService.sendEmails([email]) } [...]
Et voilà comment en quelques minutes on peut avoir une application, basique certes… mais sécurisée !
Pour aller plus loin
Le plugin Grails Spring Security possède de nombreuses autres options. Je n’ai développé ici que la stratégie de stockage des règles de sécurité dans la base, mais il est également possible de les définir directement dans le fichier SecurityConfig
, ou par annotations des méthodes des contrôleurs.
On peut appuyer la sécurité sur OpenID, LDAP, CAS, NTLM ou même utiliser une connexion FaceBook Connect. On peut changer l’algorithme de cryptage des mots de passe, les possibilités sont assez étendues.
Et si vraiment Spring Security ne vous convient pas, il existe d’autres solutions de sécurité à base de plugins comme Shiro ou Stark, qui feront peut-être l’objet d’autres articles dans le futur.
Conclusion
L’utilisation du plugin Grails Spring Security permet de mettre le pied à l’étrier très rapidement, en s’appuyant sur un standard des frameworks de sécurité en Java. J’ai personnellement beaucoup apprécié la simplicité de prise en main et les exemples fournis dans la documentation officielle. Je vous invite d’ailleurs à la parcourir, elle contient d’autres tutoriels notamment pour l’utilisation de OpenID et LDAP.
Nota Bene : Cet article est fortement inspiré de celui-ci, mais il méritait des précisions à mon goût.
Ressources :
Commentaire
11 réponses pour " Grails Spring Security Plugin, la sécurité facile "
Published by Piwaï , Il y a 13 ans
Merci pour cet article, je comptai justement me pencher sur l’intégration Spring Sec / Grails, visiblement les auteurs du plugin Grails ont fait du bon boulot !
A propos des extensions du plugin, par exemple pour intégrer CAS, c’est par ici : http://www.grails.org/AcegiSecurity+Plugin+-+Customizing+with+SecurityConfig
Published by Stéphane Maldini , Il y a 13 ans
Attention toutefois le plugin n’a pas évolué depuis plusieurs mois. On a bon espoir que le développement reprenne avec la récente intégration d’un des auteurs dans l’équipe core grails.
Il est trés intéressant d’étudier l’alternative Apache Shiro qui a l’avantage de proposer une sécurité ACL facile et l’implémentation de nouvelles sources d’authentification sympathique.
Published by Piwaï , Il y a 13 ans
Dans mon commentaire précédent, j’avais parlé d’intégrer CAS grâce à ce plugin, c’est désormais l’objet d’un article de blog : http://blog.excilys.com/2010/05/06/cas-et-grails-sans-sarcasmes/ .
Merci encore une fois pour cet article qui m’a fait découvrir ce plugin sympathique :-) .
Published by Stan , Il y a 13 ans
Merci Bcp pour cet article qui me permet d’avoir une base sur Grails.
Cependant, j’ai un petit souci : Je désire utiliser le smtp de gmail pour pouvoir
envoyer le mail de confirmation mais j’ai cette erreur :
« Could not connect to SMTP host: smtp.gmail.com, port: 465, response: -1 »
Mon code dans grails-app/conf/SecurityConfig.groovy est le suivant:
********************************************************************
defaultRole = ‘ROLE_USER’
useMail = true
mailUsername = ‘myLogin@gmail.com’
mailPassword = ‘myPassword’
mailHost = ‘smtp.gmail.com’
mailProtocol = ‘smtp’
mailFrom = ‘myLogin@gmail.com’
mailPort = 465
********************************************************************
J’ai parcouru la toile et toujours rien.
Pourriez vous s’il vous plait m’accorder votre aide.
Merci d’avance,
Stan
Published by Stan , Il y a 13 ans
Hello à tous,
solution trouvée :
Pour Gmail
Port 465 => POP
Port 587 => SMTP
NB: Ne pas oublier le mail properties
******************************************************************************
useMail = true
mailHost = ‘smtp.gmail.com’
mailPort = 587
mailUsername = ‘myLogin@gmail.com’
mailPassword = ‘mmyPassword’
mailProps = [« mail.smtp.auth »:’true’, »mail.smtp.socketFactory.port »:’587′, »mail.smtp.socketFactory.class »:’javax.net.ssl.SSLSocketFactory’, »mail.smtp.socketFactory.fallback »:’false’]
mailFrom = ‘myLogin@gmail.com’
******************************************************************************
Encore merci pour ce tuto ;-).A+
Published by Aurélien Maury , Il y a 13 ans
J’étais en train de rédiger mon coup de pouce pour GMail quand j’ai vu arrivé le dernier commentaire. Ravi de savoir que cet article a servi de façon concrète au lieu de simplement alimenter les archives du blog.
Published by Stan , Il y a 13 ans
Bonjour à tous,
je reviens vers vous car j’ai une « petite » question…
L’envoi de mail de confirmation fonctionne : Ok.
Mais si à présent, il y a des plaisantins qui s’amusent
à rentrer de fausses adresses …Pas cool!!
Comment me serait il possible de mettre en place une validation de leurs
comptes par mail??
C’est à dire une fois qu’ils auront cliqué sur le lien que je leur ai envoyé.
Votre aide me ferait un grand bien :-(..
Merci d’avance
Published by Stan , Il y a 13 ans
:-) ;-)!!
Bonjour à tous,
Solution trouvée en utilisant le plugin email-confirmation.
ce dernier envoi un lien sur lequel l’internaute devra cliquer pour
confirmer son adresse mail.
Une fois la confirmation effectuée, Acegi se charge du mail de confirmation
certifiant que l’internaute peut se connecter au site.
Portez vous bien
Stan
Published by Stan , Il y a 13 ans
;-) Hello,
Suis actuelmnt sur un projet grails et là je me heurte à un problème en base de données :Je voudrai éviter que les éléments saisis par un utilisateur X soit visible par un utilisateur Y et vise versa mais j’y arrive pas.
Mon soucis n’a rien à voir avec le tuto ci dessus et je m’en excuse cependant votre aide me fera le plus grand bien.
Merci d’avance