The mandate
Play 2 - Installation de SecureSocial

Play 2 - Installation de SecureSocial

Catégorie: Programmation.
Posté par le 27/08/2014.
Dernière mise à jour le 02/09/2014.

Description

Ce tutoriel vous expliquera comment installer le plugin SecureSocial de Play 2 en java et l’utiliser afin de gérer la connexion de vos utilisateurs.

Introduction

Ce tutoriel peut être réalisé à l'aide d'un simple éditeur de texte comme le « bloc note » ou d'un IDE tels « qu'Eclipse » ou  « Netbeans ». Il nécessite des connaissances de base en Java et que Play 2 soit installé correctement.

SecureSocial est un module de connexion pour les applications Play Framework 2. Il supporte « OAuth », « OAuth2 », « OpenID », « login/mot de passe » ainsi que des systèmes d'authentification personnalisé. Il est écrit en scala mais possède un API java. Dans ce tutoriel, nous allons expliquer comment intégrer SecureSocial à notre application Java Play 2.

Installation de SecureSocial

Nous commençons par inclure SecureSocial dans les dépendances de notre projet java. Pour ce faire, ajoutez ceci dans « /build.sbt »:

build.sbt

libraryDependencies ++= Seq(
  javaJdbc,
  javaEbean,
  cache,
  javaWs,
  "ws.securesocial" %% "securesocial" % "3.0-M1"
)

NB: Comme vous pouvez le voir ci-dessus, nous allons utiliser la version "3.0-M1" du plugin SecureSocial

Configuration de SecureSocial

Nous allons maintenant configurer SecureSocial. Pour ce faire, créez le fichier « /conf/securesocial.conf »:

securesocial.conf

smtp {
   host=send.one.com
   #port=25
   ssl=true
   user="tuto@tutorielsenfolie.com"
   password="abcdefg"
   from="tuto@tutorielsenfolie.com"
}

securesocial {
   onLoginGoTo=/
   onLogoutGoTo=/login
   ssl=false
   #assetsController=controllers.ReverseMyCustomAssetsController

   cookie {
      #name=id
      #path=/
      #domain=some_domain
      #httpOnly=true
      #idleTimeoutInMinutes=30
      #absoluteTimeoutInMinutes=720

   }

   userpass {
      withUserNameSupport=false
      sendWelcomeEmail=true
      enableGravatarSupport=true
      signupSkipLogin=true
      tokenDuration=60
      tokenDeleteInterval=5
      minimumPasswordLength=8
      enableTokenJob=true
      hasher=bcrypt
   }

   twitter {
      requestTokenUrl="https://twitter.com/oauth/request_token"
      accessTokenUrl="https://twitter.com/oauth/access_token"
      authorizationUrl="https://twitter.com/oauth/authenticate"
      consumerKey=ma_key
      consumerSecret=mon_secret
   }
}

Nous allons maintenant inclure la configuration de SecureSocial à la configuration de notre application. Pour ce faire, ajoutez la ligne suivante à « /conf/application.conf »:

application.conf

include "securesocial.conf"

Configuration de l'environment

Afin d'utiliser notre propre système de stockage d'utilisateur et d'activer l'authentification pour twitter. Nous allons créer un fichier « /app/service/MyEnvironment.scala ». Pour ce faire, ajoutez le code suivant à votre class scala:

MyEnvironment.scala

package service

import securesocial.core.RuntimeEnvironment
import securesocial.core.services.UserService
import models.User;

import scala.collection.immutable.ListMap;
import securesocial.core.providers.UsernamePasswordProvider;
import securesocial.core.providers.TwitterProvider;

class MyEnvironment extends RuntimeEnvironment.Default[User] {
   override val userService: UserService[User] = new InMemoryUserService()
 
   override lazy val providers = ListMap(
      include(new UsernamePasswordProvider[User](userService, avatarService, viewTemplates, passwordHashers)),
      include(new TwitterProvider(routes, cacheService, oauth1ClientFor(TwitterProvider.Twitter))))
}

Comme vous pouvez le voir ci-dessus, nous utilisons deux fournisseurs d'accès, « Twitter » et « login/mot de passe ».

Enregistrement de l'environnement

Nous allons enregistrer notre environnement en tant que configuration globale de notre application afin de pouvoir l'utiliser lors de la gestion des utilisateurs. Pour ce faire, créez le fichier « /app/Global.java » :

Global.java

import play.GlobalSettings;
import securesocial.core.RuntimeEnvironment;
import service.MyEnvironment;

import java.util.HashMap;

public class Global extends GlobalSettings{
    private RuntimeEnvironment env = new MyEnvironment();
    private HashMap<String, Object> instances = new HashMap<>();

    @Override
    public <A> A getControllerInstance(Class<A> controllerClass) throws Exception{
        A result = (A) instances.get(controllerClass.getName());
        if(result == null){
            try{
                result = controllerClass.getDeclaredConstructor(RuntimeEnvironment.class)
.newInstance(env);
            }catch(NoSuchMethodException e){
                // the controller does not receive a RuntimeEnvironment, delegate creation to base class.
                result = super.getControllerInstance(controllerClass);
            }
            instances.put(controllerClass.getName(), result);
        }
        return result;
    }
}

Gestion des utilisateurs

Nous allons maintenant créer une class User qui représentera notre utilisateur. Pour ce faire, créez le fichier « /app/models/User.java »:

User.java

package models;
import securesocial.core.BasicProfile;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class User implements Serializable {
    public BasicProfile main;
    public List<BasicProfile> identities;
    
    public User(BasicProfile user) {
        this.main = user;
        identities = new ArrayList<>();
        identities.add(user);
    }
}

Afin de gérer l'enregistrement et la vérification de mot de passe de nos utilisateurs « login/mot de passe », nous allons créer un service de gestion d'utilisateurs. Pour ce faire, créez le fichier « /app/service/InMemoryUserService.java » :

InMemoryUserService.java

package service;

import play.libs.F;
import securesocial.core.BasicProfile;
import securesocial.core.PasswordInfo;
import securesocial.core.services.SaveMode;
import securesocial.core.java.BaseUserService;
import securesocial.core.providers.UsernamePasswordProvider;
import securesocial.core.java.Token;

import models.User;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class InMemoryUserService extends BaseUserService<User>{
    private HashMap<String, User> users = new HashMap<String, User>();
    private HashMap<String, Token> tokens = new HashMap<String, Token>();

    @Override
    public F.Promise<User> doSave(BasicProfile profile, SaveMode mode){
        User result = null;
        if(mode == SaveMode.SignUp()){
            result = new User(profile);
            users.put(profile.providerId() + profile.userId(), result);
        }else if(mode == SaveMode.LoggedIn()){
            for(Iterator<User> it =  users.values().iterator() ; it.hasNext() && result == null ;){
                User user = it.next();
                for(BasicProfile p : user.identities){
                    if(p.userId().equals(profile.userId()) && p.providerId().equals(profile.providerId())){
                        user.identities.remove(p);
                        user.identities.add(profile);
                        result = user;
                        break;
                    }
                }
            }
        }else if(mode == SaveMode.PasswordChange()){
            for(Iterator<User> it =  users.values().iterator() ; it.hasNext() && result == null ;){
                User user = it.next();
                for(BasicProfile p : user.identities){
                    if(p.userId().equals(profile.userId()) && p.providerId().equals(UsernamePasswordProvider.UsernamePassword())){
                        user.identities.remove(p);
                        user.identities.add(profile);
                        result = user;
                        break;
                    }
                }
            }
        }else{
            throw new RuntimeException("Unknown mode");
        }
        return F.Promise.pure(result);
    }

    
    // Linking multiple social accounts to a single user
    @Override
    public F.Promise<User> doLink(User current, BasicProfile to){
        User target = null;

        for(User u: users.values()){
            if(u.main.providerId().equals(current.main.providerId()) && u.main.userId().equals(current.main.userId())){
                target = u;
                break;
            }
        }

        if(target == null){
            // this should not happen
            throw new RuntimeException("Can't find user : " + current.main.userId());
        }

        boolean alreadyLinked = false;
        for(BasicProfile p : target.identities){
            if(p.userId().equals(to.userId()) && p.providerId().equals(to.providerId())){
                alreadyLinked = true;
                break;
            }
        }
        if(!alreadyLinked) target.identities.add(to);
        return F.Promise.pure(target);
    }

    @Override
    public F.Promise<Token> doSaveToken(Token token){
        tokens.put(token.uuid, token);
        return F.Promise.pure(token);
    }

    @Override
    public F.Promise<BasicProfile> doFind(String providerId, String userId){
        BasicProfile found = null;

        for(User u: users.values()){
            for(BasicProfile i : u.identities){
                if(i.providerId().equals(providerId) && i.userId().equals(userId)){
                    found = i;
                    break;
                }
            }
        }

        return F.Promise.pure(found);
    }

    @Override
    public F.Promise<PasswordInfo> doPasswordInfoFor(User user){
        throw new RuntimeException("not yet implemented");
    }

    @Override
    public F.Promise<BasicProfile> doUpdatePasswordInfo(User user, PasswordInfo info){
        throw new RuntimeException("not yet implemented");
    }

    @Override
    public F.Promise<Token> doFindToken(String tokenId){
        return F.Promise.pure(tokens.get(tokenId));
    }


    @Override
    public F.Promise<BasicProfile> doFindByEmailAndProvider(String email, String providerId){
        BasicProfile found = null;

        for(User u: users.values()){
            for(BasicProfile i : u.identities){
                if(i.providerId().equals(providerId) && i.email().isDefined() && i.email().get().equals(email)){
                    found = i;
                    break;
                }
            }
        }

        return F.Promise.pure(found);
    }

    @Override
    public F.Promise<Token> doDeleteToken(String uuid){
        return F.Promise.pure(tokens.remove(uuid));
    }

    @Override
    public void doDeleteExpiredTokens(){
        Iterator<Map.Entry<String,Token>> iterator = tokens.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry<String, Token> entry = iterator.next();
            if(entry.getValue().isExpired()){
                iterator.remove();
            }
        }
    }
}

Cette classe est assez longue mais les méthodes les plus importantes sont « doSave » et « doFind » qui permettent de sauvegarder ou de retrouver un utilisateur

NB: Cette implémentation, enregistre les utilisateurs en mémoire vive, aucun base de données n'est utilisée.

Protéger nos pages

Nous pouvons maintenant protéger nos pages à l'aide d'annotation. Voici un exemple de protection de page:

app/controllers/Application.java

package controllers;

import play.mvc.Controller;
import play.mvc.*;
import securesocial.core.java.SecureSocial;
import securesocial.core.java.SecuredAction;
import securesocial.core.java.UserAwareAction;
import securesocial.core.BasicProfile;
import models.User;
import views.html.secure;
import views.html.index;

public class Application extends Controller {
   @UserAwareAction
   public static Result index() {
      User user = (User) ctx().args.get(SecureSocial.USER_KEY);
      String userName ;
      if(user != null){
         BasicProfile user = customUser.main;
         if(user.firstName().isDefined()){
            userName = user.firstName().get();
         }else if(user.fullName().isDefined()){
            userName = user.fullName().get();
         }else{
            userName = "authenticated user";
         }
      }else{
         userName = "guest";
      }

      return ok(index.render(userName));
   }

   @SecuredAction
   public static Result secure() {
      return ok(secure.render());
   }
}

app/models/index.scala.html

@(username: String)
Bonjour @username

app/models/secure.scala.html

utilisateur ok.

/conf/routes

GET   /secure   controllers.Application.secure()
GET   /index    controllers.Application.index()

Tu as aimé ce tutoriel ?
Aide nous à améliorer le site ! Deviens partenaire officiel ou suis nous sur facebook !

Commentaires[0]

Tu as aimé ce tutoriel ? Alors partage-le avec tes amis !
Partager sur Facebook Partager sur Twitter Partager sur Myspace Partager sur Stumbleupon Soumettre sur Reddit Partager sur Digg Ajouter à vos favoris Technorati Ajouter à vos favoris Live Ajouter à vos favoris Google Ajouter sur vos favoris Yahoo Voir le flux rss

Mots Clés: Java OAuth OAuth2 OpenID Play 2 Play framework scala SecureSocial

Veve :
(11/04/2013 - 17:19:44)
il faut juste mettre "sudo" à la place de "su" pour exécuter la commande en root

Veve :
(11/04/2013 - 17:18:56)
Salut tu peux aller lire ce tutoriel: http://www.tutorielsenfolie.com/tutoriels-63-installation-configuration-opennebula.html Il fonctionne aussi sous ubuntu

safa.souissi4 :
(10/04/2013 - 20:58:13)
s'il vous plait c urgent :(

safa.souissi4 :
(10/04/2013 - 20:56:25)
bonsoir,je cherche un tutos pour installer opennebula.org sous ubuntu 12.

Veve :
(18/03/2013 - 20:07:49)
oui, j'essaye de voir d'ou viens le problème.

sonde :
(18/03/2013 - 13:29:57)
re merci (j apprend un peu plus) je crois que j ai trouver pourquoi je peu pas poster si il y a ligne code impossible de poster lol

Veve :
(17/03/2013 - 21:34:49)
Salut, j'espère que ça t'a aidé.

sonde :
(17/03/2013 - 09:59:02)
pour ton aide

sonde :
(17/03/2013 - 09:57:36)
slt Veve impossible de laisser com

sonde :
(17/03/2013 - 09:56:55)
??

Demi-dieu :
(15/03/2013 - 18:41:13)
salut ^^

sonde :
(13/03/2013 - 14:49:35)
un petit coucou

Tanamoureuse :
(29/09/2011 - 06:11:08)
Je t'aime

Faire un don

Ma Publicité ici


Faire un don