Authentification Tomcat avec Mongo DB

Pour utiliser MongoDB comme source de données à l'authentification Tomcat, il faut :

  • Configurer le server.xml
  • Configurer le web.xml
  • Créer une librairie à mettre dans $CATALINA_HOME/lib (Y ajouter également le driver Mongo)
  • Modifier ses services pour qu'ils prennent en compte les rôles associés

Configurer server.xml : 

<Realm className="com.netapsys.MongoRealm.MongoRealm"

connectionString="127.0.0.1" port="27017" userDbName="NomBaseDeDonnéesMongo"userClName="NomCollectionUserMongo">

</Realm>

=> On pourrait également rendre encore plus ré-utilisable ce fonctionnement en précisant le nom du champ login/password à utiliser dans la collection

Configurer web.xml :

<security-constraint>

<web-resource-collection>

<web-resource-name>my webapp</web-resource-name>

<url-pattern>/private/*</url-pattern>

</web-resource-collection>

<auth-constraint>

<role-name>webapp-user</role-name>

</auth-constraint>

<user-data-constraint>

<transport-guarantee>NONE</transport-guarantee>

</user-data-constraint>

</security-constraint>

<login-config>

<auth-method>BASIC</auth-method>

<realm-name>My secured Webapp</realm-name>

</login-config>

Librairie : 

Il faut étendre org.apache.catalina.realm.RealmBase :

public class MongoRealm extends RealmBase

{

// Adresse de la base

private static String connectionString;

// Port de la base

private static int port;

// Nom de la base

private static String userDbName;

// Collection qui contient les login/mdp

private static String userClName;

private static Mongo mongo;

private static DB database;

// Users

private static DBCollection userCollection;

public static DBCollection getUserCollection()

{

if(userCollection==null)

{

try

{

mongo = new MongoClient(connectionStringport);

}

catch (UnknownHostException e)

{

e.printStackTrace();

}

database = mongo.getDB(userDbName);

userCollection = database.getCollection(userClName);

}

return userCollection;

}

public static void setUserCollection(DBCollection userCollection) {

MongoRealm.userCollection = userCollection;

}

public String getConnectionString() {

return connectionString;

}

public void setConnectionString(String connectionString) {

MongoRealm.connectionString = connectionString;

}

public int getPort() {

return port;

}

public void setPort(int port) {

MongoRealm.port = port;

}

public String getUserDbName() {

return userDbName;

}

public void setUserDbName(String userDbName) {

MongoRealm.userDbName = userDbName;

}

public String getUserClName() {

return userClName;

}

public void setUserClName(String userClName) {

MongoRealm.userClName = userClName;

}

@Override

protected String getName() {

return this.getClass().getSimpleName();

}

@Override

protected String getPassword(final String username)

{

String password = "";

DBObject myDoc = getUserCollection().findOne(new BasicDBObject("email", username));

if(myDoc!=null)

password=(String) myDoc.get("passwordhash");

return password;

}

@Override

@SuppressWarnings("unchecked")

protected Principal getPrincipal(final String username)

{

String password = "";

List<String> roles = new ArrayList<String>();

DBObject myDoc = getUserCollection().findOne(new BasicDBObject("email", username));

if(myDoc!=null)

{

password=(String) myDoc.get("passwordhash");

roles=(List<String>) myDoc.get("roles");

}

return new GenericPrincipal(username, password, roles);

}

Services :

Pour des services REST, il faut avoir 2 services de base :

Le premier accessible sans authentification pour permettre à l'utilisateur de créer son compte :

@Path("public")

public class PublicService

{

// CREATE USER

@POST

@Path("/user")

@Consumes(MediaType.APPLICATION_JSON)

@Produces(MediaType.APPLICATION_JSON)

public Success createUser(User user)

{

DAO.insertUser(user);

Success success = new Success();

success.setCode(0);

success.setDetails("Compte : " + user.getEmail());

success.setTitle("Compte créé");

return success;

}

}

Le second avec authentification pour se connecter à la partie privée :

@Path("private/user")

@DeclareRoles({"webapp-user"})

public class UserService

{

// TEST

@GET

@Path("/test")

@RolesAllowed({"webapp-user"})

public String test(@Context HttpServletRequest req)

{

return "Hello World" + req.getUserPrincipal();

}

}

Pour créer un compte, avec votre application client REST favorite : 

Créer le compte :

http://localhost:8080/PROJET/rest/public/user

Dans le body de type application/json :

{"email":"email@netapsys.fr","passwordhash":"888da5db853449fff82b07cbdbf7c755ece0783aa670bb36cc5c4cc9a68fb864"}

Pour se connecter à la partie privée :

http://localhost:8080/PROJET/rest/private/user/test

Saisir le login/hash

Elements à revoir/compléter/modifier : 

  • Saler le Hash
  • Rendre encore plus réutilisable la librairie

2 commentaires

  1. Bonjour,
    merci pour cet article très utile !

    le paragraphe ci dessous est en double au début de l’article

    Pour utiliser MongoDB comme source de données à l’authentification Tomcat, il faut :
    Configurer le server.xml
    Configurer le web.xml
    Créer une librairie à mettre dans $CATALINA_HOME/lib (Y ajouter également le driver Mongo)
    Modifier ses services pour qu’ils prennent en compte les rôles associés

    Cordialement

  2. attention également au doubles quote (« ) converties en guillemets («) dans le bloc de code

    il devrai être

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.