Index: main/workspace-cms/src/org/ametys/cms/workspace/LoginFormGenerator.java
===================================================================
--- main/workspace-cms/src/org/ametys/cms/workspace/LoginFormGenerator.java	(revision 26836)
+++ main/workspace-cms/src/org/ametys/cms/workspace/LoginFormGenerator.java	(working copy)
@@ -16,13 +16,23 @@
 package org.ametys.cms.workspace;
 
 import java.io.IOException;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
 
 import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
 import org.apache.cocoon.generation.AbstractGenerator;
 import org.apache.cocoon.xml.XMLUtils;
+import org.joda.time.DateTime;
 import org.xml.sax.SAXException;
 
 import org.ametys.runtime.config.Config;
+import org.ametys.runtime.datasource.ConnectionHelper;
 import org.ametys.runtime.plugins.core.authentication.FormBasedCredentialsProvider;
 
 /**
@@ -32,8 +42,13 @@
 public class LoginFormGenerator extends AbstractGenerator
 {
 
+    /** Time allowed to delete data into the BDD (days) */
+    public static final Integer TIME_ALLOWED = 1;
+    
     public void generate() throws IOException, SAXException, ProcessingException
     {
+        _deleteAllPastLoginFailedBDD();
+        
         String level = Config.getInstance().getValueAsString("runtime.authentication.form.security.level");
         
         boolean autoComplete = false;
@@ -42,9 +57,13 @@
         
         if (FormBasedCredentialsProvider.SECURITY_LEVEL_HIGH.equals(level))
         {
+            Request request = ObjectModelHelper.getRequest(objectModel);
+            String login = request.getParameter("login");
+            int nbConnect = _requestNbConnectBDD(login);
+            
+            captcha = nbConnect >= 3;
             autoComplete = false;
             rememberMe = false;
-            captcha = true;
         }
         else if (FormBasedCredentialsProvider.SECURITY_LEVEL_LOW.equals(level))
         {
@@ -63,5 +82,90 @@
         XMLUtils.endElement(contentHandler, "LoginForm");
         contentHandler.endDocument(); 
     }
+    
+    /**
+     * Get the number of failed connections with this login
+     * @param login
+     * @return nbConnect
+     */
+    protected Integer _requestNbConnectBDD(String login)
+    {
+        Connection con = null;
+        PreparedStatement stmt = null;
+        ResultSet rs = null;
+        try
+        {
+            // Effectuer la connexion à la base de données
+            con = ConnectionHelper.getConnection(ConnectionHelper.CORE_POOL_NAME);    
+            
+            // Contruire la requête pour authentifier l'utilisateur
+            String sql = "SELECT nb_connect FROM Users_FormConnectionFailed WHERE login = ?";
+            
+            stmt = con.prepareStatement(sql);
+            stmt.setString(1, login);
+    
+            // Effectuer la requête
+            rs = stmt.executeQuery();
+    
+            Integer nbConnect = 0;
+            if (rs.next()) 
+            {
+                nbConnect = rs.getInt("nb_connect"); 
+            }
+            return nbConnect;
+        }
+        catch (SQLException e)
+        {
+            getLogger().error("Error during the connection to the database", e);
+            return 0;
+        }
+        finally
+        {
+            // Fermer les ressources de connexion
+            ConnectionHelper.cleanup(rs);
+            ConnectionHelper.cleanup(stmt);
+            ConnectionHelper.cleanup(con);
+        }
+    }
+    
+    /**
+     * Delete all past failed connections
+     */
+    protected void _deleteAllPastLoginFailedBDD()
+    {
+        Connection con = null;
+        PreparedStatement stmt = null;
+        ResultSet rs = null;
+        try
+        {
+            // Effectuer la connexion à la base de données
+            con = ConnectionHelper.getConnection(ConnectionHelper.CORE_POOL_NAME);    
+            
+            // Contruire la requête pour authentifier l'utilisateur
+            String sql = "DELETE FROM Users_FormConnectionFailed WHERE last_connect < ?";
+            
+            stmt = con.prepareStatement(sql);
+            
+            DateTime dateToday = new DateTime();
+            DateTime pastDate = dateToday.minusDays(TIME_ALLOWED);
+            Timestamp date = new Timestamp(pastDate.getMillis());
+            stmt.setTimestamp(1, date);
+            
+            // Effectuer la requête
+            stmt.execute();
+        }
+        catch (SQLException e)
+        {
+            getLogger().error("Error during the connection to the database", e);
+        }
+        finally
+        {
+            // Fermer les ressources de connexion
+            ConnectionHelper.cleanup(rs);
+            ConnectionHelper.cleanup(stmt);
+            ConnectionHelper.cleanup(con);
+        }
+        
+    }
 
 }
Index: main/workspace-cms/i18n/messages_en.xml
===================================================================
--- main/workspace-cms/i18n/messages_en.xml	(revision 26836)
+++ main/workspace-cms/i18n/messages_en.xml	(working copy)
@@ -39,6 +39,7 @@
 	<message key="WORKSPACE_CMS_LOGIN_REMEMBER_ME">Remember password</message>
 	<message key="WORKSPACE_CMS_LOGIN_FAILED">Username or login incorrect</message>
 	<message key="WORKSPACE_CMS_LOGIN_FAILED_WITH_CAPTCHA">Username, login or image text incorrect</message>
+	<message key="WORKSPACE_CMS_LOGIN_FAILED_MANY_TIME">Fill the image text because of too many attempts for this user</message>
 	<message key="WORKSPACE_CMS_LOGIN_CONNECT">Connection</message>
 	
 	<!-- +
Index: main/workspace-cms/i18n/messages_fr.xml
===================================================================
--- main/workspace-cms/i18n/messages_fr.xml	(revision 26836)
+++ main/workspace-cms/i18n/messages_fr.xml	(working copy)
@@ -39,6 +39,7 @@
 	<message key="WORKSPACE_CMS_LOGIN_REMEMBER_ME">Se souvenir du mot de passe</message>
 	<message key="WORKSPACE_CMS_LOGIN_FAILED">Nom d'utilisateur ou mot de passe incorrect</message>
 	<message key="WORKSPACE_CMS_LOGIN_FAILED_WITH_CAPTCHA">Nom d'utilisateur, mot de passe ou texte de l'image incorrect</message>
+	<message key="WORKSPACE_CMS_LOGIN_FAILED_MANY_TIME">Remplissez le texte de l'image car il y a eu trop d'erreurs de connexion sur cet utilisateur</message>
 	<message key="WORKSPACE_CMS_LOGIN_CONNECT">Connexion</message>
 	
 	<!-- +
Index: main/workspace-cms/stylesheets/login.xsl
===================================================================
--- main/workspace-cms/stylesheets/login.xsl	(revision 26836)
+++ main/workspace-cms/stylesheets/login.xsl	(working copy)
@@ -24,6 +24,7 @@
     <xsl:import href="plugin:core://stylesheets/helper/common.xsl"/> 
     
     <xsl:param name="login-failed"/>
+    <xsl:param name="tooManyAttempts"/>
     
     <xsl:param name="contextPath"/>
     <xsl:param name="workspaceName"/>
@@ -35,7 +36,7 @@
     <xsl:template match="/LoginForm">
     	<xsl:variable name="formHeight">
     		<xsl:choose>
-    			<xsl:when test="useCaptcha = 'true'">230</xsl:when>
+    			<xsl:when test="useCaptcha = 'true'">240</xsl:when>
     			<xsl:otherwise>185</xsl:otherwise>
     		</xsl:choose>
     	</xsl:variable>
@@ -144,6 +145,7 @@
 		    			<xsl:if test="$login-failed = 'true'">
 		    				<span class="error">
 		    					<xsl:choose>
+		    						<xsl:when test="$tooManyAttempts = 'true'"><i18n:text i18n:key="WORKSPACE_CMS_LOGIN_FAILED_MANY_TIME" i18n:catalogue="workspace.cms"/></xsl:when>
 		    						<xsl:when test="useCaptcha = 'true'"><i18n:text i18n:key="WORKSPACE_CMS_LOGIN_FAILED_WITH_CAPTCHA" i18n:catalogue="workspace.cms"/></xsl:when>
 		    						<xsl:otherwise><i18n:text i18n:key="WORKSPACE_CMS_LOGIN_FAILED" i18n:catalogue="workspace.cms"/></xsl:otherwise>
 		    					</xsl:choose>
Index: main/workspace-cms/sitemap.xmap
===================================================================
--- main/workspace-cms/sitemap.xmap	(revision 26836)
+++ main/workspace-cms/sitemap.xmap	(working copy)
@@ -97,11 +97,12 @@
             </map:match>
             
             <map:match pattern="login_failed.html">
-                 <map:generate type="login-form" label="content"/>
+                <map:generate type="login-form" label="content" />
                 <map:transform type="xslt" src="stylesheets/login.xsl">
 					<map:parameter name="contextPath" value="{request:contextPath}"/>
 					<map:parameter name="workspaceURI" value="{request-attr:workspaceURI}"/>
 					<map:parameter name="workspaceName" value="{request-attr:workspaceName}"/>
+					<map:parameter name="tooManyAttempts" value="{request-param:tooManyAttempts}"/>
 					<map:parameter name="login-failed" value="true"/>
 				</map:transform>
                 <map:transform type="i18n" label="xml">
