jeudi 17 juillet 2014

Sécurisez votre application avec Spring Security


Spring Security, petit frère d'Acegi Security, est un framework qui fournit des mécanismes d'authentification et de sécurisation pour vos applications Java. Voici les trois étapes pour sécuriser votre appli web.

Configuration dans le web.xml

Le fichier web.xml est le descripteur de déploiement de votre application web.
Il est généralement situé dans le répertoire WEB-INF et définit les paramètres de base de votre application.

Commençons par définir un filtre de type FilterChainProxy dans le fichier web.xml.

<filter>
  <filter-name>My Spring Security Filter Chain Proxy</filter-name>
  <filter-class>org.springframework.security.web.FilterChainProxy</filter-class>
  <init-param>
    <param-name>targetBean</param-name>
    <param-value>springSecurityFilterChainProxy</param-value>
  </init-param>
</filter>

Puis définissez dessous les URLs concernées par ce filtre.

<filter-mapping>
  <filter-name>My Spring Security Filter Chain Proxy</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

Dans notre exemple, l'intégralité des URLs de l'application sont traitées par le filtre de Spring Security.

Création d'un fichier de configuration séparé

Créez un fichier de configuration applicationContext-security.xml puis référencez le dans votre web.xml.

<import resource="classpath:applicationContext-security.xml"/>

Et collez-y le contenu suivant

<?xml version="1.0" encoding="UTF-8"?>

<beans:beans xmlns=http://www.springframework.org/schema/security
xmlns:beans="http://www.springframework.org/schema/beans" xmlnssi=http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schem...-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">

   <!-- Ici les filtres, dans la prochaine étape... -->

</beans:beans>

Création des filtres de sécurité


Paramétrage de la chaîne de filtres

Le filtre définie dans votre fichier de configuration est un bean de type FilterChainProxy
Ce type définit une chaîne de filtre paramétrable par URL, ce qui permet une gestion des filtres et des droits relativement fine. On précise la liste et l'ordre des filtres Spring Security appliqués par pattern d'URLs.

A l'opposé, la chaîne DelegatingFilterProxy appliquera l'intégralité des filtres sur l'ensemble des URLs.

Ci-dessous est présenté un bean de type FilterChainProxy avec trois paramétrages de filtres différents.

<beans:bean id="springSecurityFilterChainProxy" class="org.springframework.security.web.FilterChainProxy">
  <beans:constructor-arg>
  <beans:list>
    <filter-chain pattern="/clog**" filters="httpSessionContextIntegrationFilter" />
    <filter-chain pattern="/log/**" filters="httpSessionContextIntegrationFilter" />
    <filter-chain pattern="/**" filters="httpSessionContextIntegrationFilter,exceptionTranslationFilter,filterSecurityInterceptor" />
  </beans:list>
  </beans:constructor-arg>
</beans:bean>

Les URLs respectant le patterne "/clog**" ou "/log/**" sont filtrées par un filtre unique définit dans le bean portant le nom httpSessionContextIntegrationFilter.

Les autres URLs sont filtrées par trois filtres définis dans les beans portant les noms httpSessionContextIntegrationFilter, exceptionTranslationFilter et filterSecurityInterceptor.


Les filtres les plus utilisés


1 - Le filtre SecurityContextPersistenceFilter

Le filtre SecurityContextPersistenceFilter joue un double rôle.

Il est chargé de lier le contexte de sécurité (SecurityContext) à la session lors des requêtes HTTP. Le contexte de sécurité peut s'initialiser à l'aide du code Java suivant

SecurityContextHolder.getContext().setAuthentication(authManager)

authManager est un objet de type org.springframework.security.authentication.AuthenticationManager

Il est également chargé de supprimer le contexte de sécurité de la session HTTP lorqu'un utilisateur se déconnecte. Le contexte de sécurité peut être supprimé à l'aide du code Java suivant

SecurityContextHolder.clearContext();

En configuration de base, le filtre peut être créé sans paramètres comme ci-dessous.

<beans:bean id="httpSessionContextIntegrationFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>


2 - Le filtre ExceptionTranslationFilter

Le filtre ExceptionTranslationFilter est chargé de détecter les exceptions levées par Spring Security. Ces exceptions seront généralement déclenchées par l'objet AbstractSecurityInterceptor qui est le fournisseur principal des services d'autorisation. Dès lors, si une requête est effectuée sur une URL non autorisée, une erreur d'autorisation sera levée puis récupérée par le filtre ExceptionTranslationFilter.

Dans un cas d'utilisation standard, il est fréquent de renseigner la propriété authenticationEntryPoint, ce qui aura pour effet de réorienter toutes les requêtes non autorisées vers une page d'entrée (ie login).

Le filtre peut être créé avec la configuration suivante.

<beans:bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
<beans:property name="authenticationEntryPoint">
<beans:bean class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/start/index.jsp" />
</beans:bean>
</beans:property>
</beans:bean>

3 - Le filtre FilterSecurityInterceptor

Le filtre FilterSecurityInterceptor est chargé de filtrer les URLs par profil d'utilisateur.

La création du filtre s'effectue en trois étapes :
  • Création d'un manager d'authentification
  • Création d'un manager d'accès
  • Création d'une liste d'URLs par rôle
Il peut être crée avec la configuration suivante :

<beans:bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
  <beans:property name="authenticationManager" ref="authenticationManager" />
  <beans:property name="accessDecisionManager" ref="accessDecisionManager" />
  <beans:property name="securityMetadataSource">
    <filter-security-metadata-source>
      [...]
    </filter-security-metadata-source>
  </beans:property>
</beans:bean>

Un manager d'authentification peut être créé avec la configuration suivante.

<authentication-manager alias="authenticationManager">
  <authentication-provider user-service-ref="dbAuthProvider" >
    <password-encoder hash="md5" />
  </authentication-provider>
  <authentication-provider ref="ldapAuthProvider">
    <password-encoder hash="plaintext" />
  </authentication-provider>
</authentication-manager>

On définit une liste de providers qui seront appelés dans l'ordre dans lesquels ils sont définis dans le fichier XML. Dans cet exemple, une première authentification est effectuée sur une base de donnée avant d'interroger un annuaire LDAP en cas d'échec sur la base de données.

Un manager d'accès peut être créé avec la configuration suivante.

<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
  <beans:property name="allowIfAllAbstainDecisions">
    <beans:value>false</beans:value>
  </beans:property>
  <beans:property name="decisionVoters">
    <beans:list>
      <beans:bean id="authVoter" class="org.springframework.security.access.vote.AuthenticatedVoter"></beans:bean>
      <beans:bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter">
        <beans:property name="rolePrefix">
          <beans:value></beans:value>
        </beans:property>
      </beans:bean>
    </beans:list>
  </beans:property>
</beans:bean>

Enfin la liste des URLs est définie en utilisant des balises <intercept-url> à l'intérieur de la balise <filter-security-metadata-source>. Ci-dessous sont présentés des exemples d'URLs filtrées.

<intercept-url pattern="/log/**" access="permitAll" />
<intercept-url pattern="/forbidden/**" access="denyAll" />
<intercept-url pattern="/pro/pro_110.do" access="hasAnyRole('superviseur','gestionnaire')" />
<intercept-url pattern="/pro/pro_110.jsp" access="hasRole('superviseur')" />

Aucun commentaire:

Enregistrer un commentaire

Un avis ? Une question ?
N'hésitez pas à laissez des commentaires !