Pages

samedi 15 novembre 2014

Sécuriser une application avec Spring Security

Comme j'ai fait plusieurs articles dernièrement sur comment migrer une application Spring configurée en XML vers une application configurée en Java je vais aujourd'hui aborder la sécurité.

Spring Security est un module incontournable d’une application développée en Spring. Il apporte tout le nécessaire pour sécuriser une application et il a l’avantage d’être vraiment personnalisable. La notion de sécurité informatique n’est pas une mince affaire et sa mise en place est parfois longue et demande d’être constamment adaptée au niveau réseau, serveurs, application… Spring Security n’intervient que sur le domaine applicatif. 

Quand on parle sécurité applicative, nous avons deux notions essentielles :  l’authentification (savoir qui je suis) et les autorisations (savoir ce que j’ai le droit de faire). Spring Security essaye d’apporter une solution à ces deux problématiques.

Au niveau de l’authentification vous pouvez utiliser soit des mécanismes apportés par le framework, soit utiliser des systèmes annexes. Spring security permet par exemple de s’authentifier via un annuaire LDAP, OpenID, formulaires, JAAS, Kerberos… et bien d’autres encore. Vous pouvez même assez facilement vous connecter à votre propre système si ce dernier fournit une API quelconque.

Au dessus des mécanismes d’authentification Spring Security permet d'ajouter facilement des autorisations sur les requêtes web, les méthodes ou même des objets.

Pour configurer votre application vous pouvez utiliser soit la configuration historique en XML soit la Java Config. Cette dernière est plus qu’encouragée avec les dernières versions de Spring.


Authentification
La première étape est de créer un bean de configuration

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }
}

Lors du chargement de ce bean, un filtre de servlet (springSecurityFilterChain) est créé. C’est ce dernier qui orchestrera toute la sécurité (protection des URL, la validation login, mot de passe, ...) au sein de votre application.

Vous devez absolument définir un et un seul AuthenticationManagerBuilder dans votre application. Cette classe permet de définir quel sera le mode d’authentification des utilisateurs. La classe permettant de le créer devra être annotée soit par @EnableWebSecurity, @EnableWebMvcSecurity, @EnableGlobalMethodSecurity, ou @EnableGlobalAuthentication. Tout dépend du niveau de sécurité que vous voulez activer.

Dans l’exemple si dessus nous avons configuré un mode d’authentification ou chaque user est défini manuellement dans votre application. Par exemple ici seul l’utilisateur "user" avec le rôle "USER" peut s’authentifier.

Nous pouvons utiliser d’autres modes d’authentification et même les mixer.

@Autowired
private DataSource dataSource;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth
            .jdbcAuthentication()
            .dataSource(dataSource)
            .withDefaultSchema()
            .withUser("user").password("password").roles("USER").and()
            .withUser("admin").password("password").roles("USER", "ADMIN");
}

Par défaut plusieurs fonctionnalités sont activées par défaut
  • sécurisation de toutes le URL de l’application
  • génération d’un formulaire par défaut pour s’authentifier
  • service pour se loguer et se déloguer
  • différentes fonctionnalités pour prévenir les attaques cross domain, la fixation de session
  • ...

Autorisations
Notre classe de configuration donnée en exemple propose une configuration par défaut qui est la suivante.

protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .and()
            .httpBasic();
}

L’URL /login (via un HTTP GET) affiche le formulaire de login et l’URL /login (via une requête POST) et permet d’authentifier l’utilisateur.

C’est bien beau mais j’aimerais bien proposer mon propre formulaire pour m’authentifier. Rien de plus simple:

protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .permitAll();
}

Vous pouvez être moins restrictif ou plus restrictif sur la définition des autorisations liées aux requêtes. Par exemple :

protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/resources/**", "/signup", "/about").permitAll()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .antMatchers("/db/**").access("hasRole('ROLE_ADMIN') and hasRole('ROLE_DBA')")
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .permitAll();
}


Je viens de montrer comment sécuriser les requêtes HTTP mais vous pouvez également restreindre les droits sur vos méthodes.

public interface MyBlog {

    @Secured("ANONYME")
    public Article readArticle(Long id);

    @Secured("REDACTEUR")
    public Article write(Article article, String content);
}

Pour activer la sécurité via les annotations vous devrez ajouter l’annotation @EnableGlobalMethodSecurity dans votre classe de configuration.

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class MethodSecurityConfig {
    // ...
}

Des exemples
Sur les exemples je ne vais pas recopier les nombreux tutoriels mis à disposition par Spring et je vous réoriente vers la partie exemples de la documentation officielle.

Les possibilités offertes par Spring Security sont vastes donc n’hésitez pas à parcourir cette documentation

5 commentaires:

  1. Merci beaucoup pour ce tutoriel clair

    RépondreSupprimer
  2. Merci beaucoup pour ce tutoriel clair

    RépondreSupprimer
  3. salut :) et si je voudrai gérer des écrans de mon site en fonction des roles des utilisateurs (et chaque role a des fonctionnalités) en utilisant le spring security, comment ferai-je? merci d'avance.

    RépondreSupprimer
  4. Vraiment tres bon article. Tres clair et bien expliquer

    RépondreSupprimer

Remarque : Seul un membre de ce blog est autorisé à enregistrer un commentaire.