Saler les données en Spring

Protection supplémentaire pour les informations sensibles

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com

Certaines données dans notre système sont plus importantes que les autres. Il s'agit par exemple des mots de passes qu'on devra protéger avec une couche supplémentaire. Cette couche consistera à saler le mot de passe, c'est-à-dire, à le rendre plus difficile à deviner par un utilisateur malveillant. L'article ci-dessous présentera la technique employée dans ce but.

Saller le mot de passe dans Spring

Le sel est utilisé dans les mots de passe pour les rendre plus difficilement identifiables par les utilisateurs malveillants. Le salage consiste à rajouter une chaîne de caractères supplémentaires au mot de passe de l'utilisateur. Au mieux, il faut que ce mot soit le plus personnel possible.

Dans notre cas, le salage sera fait avec la classe SaltCellar, définie dans notre fichier de sécurité :

afficher le code

La seule chose intéressante de ce bout de code est la présence de la map qui contient les relations entre les caractères et les composants du sel. L'implémentation de ce bean se présente de la manière suivante :

public class SaltCellar implements SaltSource {
    final Logger logger = LoggerFactory.getLogger(SaltCellar.class);
    private Map<String, String> saltData;
    @Autowired
    private ShaPasswordEncoder passwordEncoder;
    
    public void setSaltData(Map<String, String> saltData) {
        logger.info("Put new salt data " + saltData);
        this.saltData = saltData;
    }
    
    /**
     * Salt is always constructed on login property.
     * @access public
     * @param UserDetails user Connected user instance.
     * @return Object Salt used in password.
     */
    public Object getSalt(UserDetails user) {
        logger.info("Getting salted password from UserDetails instance " + user);
        return getSaltFromString(user.getUsername());
    }
    
    public String getSaltFromString(String value) {
        if (value == null) return "-";
        StringBuffer salt = new StringBuffer();
        String[] loginParts = value.split("");
        for (int i = 0; i < loginParts.length; i++) {
            logger.info("Looking for " + loginParts[i]);
            if (!loginParts[i].equals("") && saltData.containsKey(loginParts[i].toLowerCase())) {
                salt.append(saltData.get(loginParts[i].toLowerCase()));
            }
        }
        logger.info("Generated salt = " + new String(salt));
        // logger.info("Encoded password = " + passwordEncoder.encodePassword("bartosz", "a"));
        logger.info("Encoded password salt = " + passwordEncoder.encodePassword("bartosz", new String(salt)));
        logger.info("Encoded password salt for admin = " + passwordEncoder.encodePassword("admin", new String(salt)));
        return new String(salt);
    }
}

La classe implémente l'interface org.springframework.security.authentication.dao.SaltSource dont la méthode getSalt() retourne le sel à rajouter dans le mot de passe. Dans notre cas, le sel est basé sur le login de l'utilisateur qui est ensuite traduit en une nouvelle chaîne de caractères. Cette nouvelle chaîne de caractères est composée par les éléments définis dans la map de notre bean.

Bartosz KONIECZNY Sécurité

Une question ? Une remarque ?

*

*

Un conseil Symfony2

Comment personnaliser l'affichage des champs du formulaire ?

Pour personnaliser l'affichage des champs du formulaire sous Symfony2 on doit surcharger le paramètre nommé templating.helper.form.class. Par défaut il s'agit de la classe Symfony\Bundle\FrameworkBundle\Templating\Helper\FormHelper. Le code se présente ainsi :

<?xml version="1.0" encoding="UTF-8" ?>
  <container xmlns="http://symfony.com/schema/dic/services"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
    <parameters>
      <parameter key="templating.helper.form.class">Frontend\FrontBundle\Helper\FormHelper
    </parameters>
  </container>
La classe surchargée va, avant d'afficher le champ, faire appel à la méthode setTheme(). Tout cela pour déterminer quel thème doit utiliser Symfony2 pour le rendu du formulaire (champ text, boutons radio etc.). Le code de cette FormHelper se présente ainsi :
namespace Frontend\FrontBundle\Helper;

use Symfony\Component\Templating\Helper\Helper;
use Symfony\Component\Templating\EngineInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Exception\FormException;
use Symfony\Component\Form\Util\FormUtil;
use Symfony\Bundle\FrameworkBundle\Templating\Helper\FormHelper as ParentHelper;

class FormHelper extends ParentHelper
{
    protected $engine;

    protected $varStack;

    protected $context;

    protected $resources;

    protected $themes;

    protected $templates;

    protected function renderSection(FormView $view, $section, array $variables = array())
    {
        // if new theme is set (for exemple for override form templates)
        if(isset($variables['attr']['theme'])) $this->setTheme($view,  $variables['attr']['theme']);
        return parent::renderSection($view, $section, $variables);
    }

}
Afin de personnaliser un champ du formulaire sous Symfony2 il faut passer un paramètre theme qui appelera la fonction setTheme. Voici un exemple :
// it will show the template located ad /app/Resources/views directory
echo $view['form']->widget($form['replyType'], array('attr' => array('theme' => array(0 => ':'))));
Pour voir comment on peut personnaliser ces champs, veuillez vous référer aux fichiers placés dans /vendor/Symfony/Bundle/FrameworkBundle/Resources/views/Form.