Comment créer une application Angular avec le rendu côté serveur ?

Gestion du rendu côté serveur : Une nouveauté Angular imposant un défi

Angular est un framework utilisant le langage de programmation TypeScript. La version 5 a été mise en ligne en novembre 2017, avec de nouvelles fonctionnalités et corrections de bugs. Cette dernière version est accompagnée de l’outil en ligne de commande Angular CLI, mais aussi de nouveautés  attendues et réellement plébiscitées par la communauté, comme la gestion du rendu côté serveur.

Un des problèmes récurrents que l’on peut rencontrer lorsque l’on met en place un site web avec une librairie moderne (Angular, React, Vue.js, etc.) est que, de manière générale, les robots ne pourront pas lire votre site. Par conséquent, si vous souhaitez partager votre article sur Facebook, ou simplement être bien référencé sur les moteurs de recherche, la partie risque d’être compliquée (bien que dans le cas de Google, il semblerait que leurs robots soient capable de lire des pages générées par Javascript depuis récemment).

La raison est simple, la plupart des robots ne savent pas à quel moment votre page sera entièrement générée par Javascript. Par conséquent, ils ne seront en mesure de lire qu’une infime partie de votre HTML, à savoir, bien souvent, un petit ‘Loading…’ pas très explicite !

Comment peut-on alors créer une application Angular avec le rendu côté serveur ?

Angular CLI

Pour pallier à ce problème, Angular CLI (l’outil qui aide à la génération d’une application Angular) peut venir à la rescousse. Également, avec la version 5 d’Angular, il est désormais possible de gérer le transfert d’état serveur vers le client. Par exemple, une application qui fait une requête à une API Rest ne fera pas la même requête deux fois (une fois côté serveur, une autre fois côté client) mais transférera le résultat côté serveur au client. Nous allons étudier ces deux cas successivement afin de pouvoir bien démarrer une application avec le rendu côté serveur.

Comment initier le projet Angular?

Démarrons en installant l’outil Angular CLI :
npm i -g @angular/cli

On initialise ensuite notre projet :
ng new ssr-app style=scss # Parce que c'est mieux avec le SCSS

On va dans le répertoire de l’application générée et on lance le serveur de développement :

cd ssr-app
ng serve

Allez sur http://localhost:4200/ et enjoy ! Maintenant, nous devons configurer la gestion du rendu côté serveur.

Comment configurer le rendu côté serveur?

Commençons par installer le package platform-server : npm i -S @angular/platform-server

Dans le fichier .angular-cli.json à la racine du projet, il faut ajouter dans la partie « apps », la configuration suivante :

{
   "name": "universal",
   "platform": "server",
   "root": "src",
   "outDir": "dist-server",
   "main": "main.server.ts",
   "tsconfig": "tsconfig.server.json",
   "environmentSource": "environments/environment.ts",
   "environments": {
      "dev": "environments/environment.ts",
      "prod": "environments/environment.prod.ts"
   }
}

Dans notre dossier src/app, on a désormais besoin d’un fichier app.server.module.ts à côté de notre fichier app.module.ts. Ce sera notre point d’entrée pour notre application côté serveur. Son contenu :

import {NgModule} from '@angular/core';
import {ServerModule} from '@angular/platform-server';

import {AppModule} from './app.module';
import {AppComponent} from './app.component';

@NgModule({
   imports: [
      AppModule,
      ServerModule
   ],
   bootstrap: [AppComponent]
})
export class AppServerModule {
}

Le fichier hérite simplement des modules du fichier app.module.ts et ajoute le module ServerModule.

Quant au fichier main.server.js renseigné dans le .angular-cli.json, nous devons le créer à côté du fichier main.ts dans le répertoire src/ avec le contenu suivant :

import {enableProdMode} from '@angular/core';
export {AppServerModule} from './app/app.server.module';

enableProdMode();

Nous devons également créer un fichier tsconfig.app.server.json pour la compilation de TypeScript à côté du tsconfig.app.json dans le même répertoire :

{
   "extends": "./tsconfig.app.json",
   "compilerOptions": {
      "outDir": "../out-tsc/server",
      "module": "commonjs"
   },
   "exclude": [
      "test.ts",
      "**/*.spec.ts"
   ],
   "angularCompilerOptions": {
      "entryModule": "app/app.server.module#AppServerModule"
   }
}

Dans le répertoire src/app, il nous faut désormais modifier le fichier app.module.ts en ajoutant une méthode à notre module BrowserModule :

import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {AppComponent} from './app.component';

@NgModule({
   declarations: [
      AppComponent
   ],
   imports: [
      BrowserModule.withServerTransition({ appId: 'universal' })
   ],
   providers: [],
   bootstrap: [AppComponent]
})
export class AppModule {
}

On peut désormais builder notre application côté serveur/côté client. Pour cela, rajoutons une ligne dans les scripts de notre package.json :

"scripts": {
   ...
   "universal": "ng build --prod && ng build --prod --app universal --output-hashing=none",
   ...
}

A quoi sert cette commande ? Tout simplement à générer d’une part, une build côté client et, d’une autre part, une build côté serveur (avec la référence à notre app configurée dans le fichier .angular-cli.json). Pour le côté serveur on enlève la création d’un hash sur le fichier généré main.bundle.js pour pouvoir y faire référence plus tard.

Si on lance la commande npm run universal, on obtient bien nos deux builds dans deux fichiers respectifs dist/ et dist-server/.

Désormais, on souhaite pouvoir lancer notre serveur. Pour l’instant, le package Universal d’Angular ne supporte que Node.js et ASP.NET. Nous allons écrire notre serveur en Node.js.

Il faut tout d’abord installer le package @nguniversal/express-engine qui permettra de bootstraper notre serveur Node.js avec le framework Express. Il suffit donc de lancer la commande npm i -S @nguniversal/express-engine.

On va ensuite écrire un fichier server.js à la racine de notre projet avec ce contenu :

require('zone.js/dist/zone-node');

const express = require('express');
const ngUniversal = require('@nguniversal/express-engine');

/**
* On charge le seul fichier de notre build côté serveur
*/
const bootstrap = require('./dist-server/main.bundle');

/**
* On crée motre instance Express
*/
const app = express();

app.get('/', (req, res) => res.render('index', {req, res}));

/**
* Obtient les fichiers statics provenant de la build dist/
*/
app.use(express.static(`${__dirname}/dist`));

/**
* Configuration de Express Engine
*/
app.engine('html', ngUniversal.ngExpressEngine({
   bootstrap: bootstrap.AppServerModuleNgFactory
}));
app.set('view engine', 'html');
app.set('views', 'dist');

/**
* Toutes les URLs renvoient à l'index.html du répertoire dist/
* Angular se charge se rediriger vers les bonnes routes
*/
app.get('*', (req, res) => res.render('index', {req, res}));

/**
* On lance notre serveur
*/
app.listen(3000, () => console.log(`Listening on http://localhost:3000`));

Champagne ! Nous avons enfin configuré notre application Angular ainsi que notre serveur Node.js.

Lancez le serveur en tapant ‘node server.js’ et accédez à l’URL http://localhost:3000. Votre page est générée côté serveur au lancement, puis prise en charge par la build côté client une fois chargée. Si vous désactivez le Javascript de votre navigateur, miracle ! Votre page est tout de même générée grâce à notre configuration.

Comment transférer l’état de l’application ?

Bien que notre application fonctionne parfaitement avec cette configuration, celle-ci n’est pas complètement optimale.

Si votre application nécessite des requêtes via une API Rest par exemple, celles-ci seront effectuées deux fois au lieu d’une. En effet, si le serveur est sollicité pour effectuer une requête, le navigateur ne le sait pas et effectuera cette même requête une seconde fois lorsque le côté serveur prendra le relai.

Pour l’exemple, nous allons commencer par ajouter le HttpClientModule dans notre app.module.ts et notre app.server.module.ts (l’idéal serait d’avoir un fichier de modules en commun, mais je vous laisse la liberté de le faire !) :

import {HttpClientModule} from '@angular/common/http';

@NgModule({
   ...
   imports: [
      ...
      HttpClientModule
   ],
   ...
})
export class AppModule {
}

Allons dans notre app.component.ts et supprimons le contenu que nous allons remplacer par :

import {Component, OnInit} from '@angular/core';
import {HttpClient} from '@angular/common/http';

@Component({
   selector: 'app-root',
   templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
   image: any;

   constructor(private http: HttpClient) {
}

ngOnInit() {
   this.http.get('http://www.splashbase.co/api/v1/images/random')
      .subscribe(data => this.image = data);
    }
}

Nous nous chargeons d’afficher une image random récupérée via une API Rest.

Pour le rendu, éditons notre fichier app.component.html que nous remplacerons par cette unique balise :

< img *ngIf="image" [src]="image.url" >

Cette image sera donc le résultat de notre requête à l’API.

Si nous démarrons une build avec npm run universal et que nous lançons notre serveur avec ‘node server.js’, nous avons bien notre page qui fonctionne correctement. Petit bémol : l’image apparaît quelques millisecondes et est remplacée par une autre image.

La raison est le même que précédemment : une requête est faite côté serveur, et une autre est faite côté client une fois la page chargée. Le requête côté client est donc inutile.

L’idée est donc de transférer l’état de notre requête vers le côté client afin de ne pas multiplier les requêtes inutiles.

Pour cela, nous allons importer le ServerTransferStateModule dans notre app.server.module.ts et le BrowserTransferStateModule dans notre app.module.ts :

/* app.server.module.ts */
import {ServerTransferStateModule} from '@angular/platform-server';

@NgModule({
   imports: [
      ServerTransferStateModule /* Ici ! */
   ],
   bootstrap: [AppComponent],
})
export class AppServerModule {}

/* app.module.ts */
import {BrowserTransferStateModule} from '@angular/platform-browser'

@NgModule({
imports: [
   ...
   BrowserTransferStateModule /* Ici ! */
   ],
   bootstrap: [AppComponent],
})
export class AppServerModule {}

Une fois la configuration effectuée, on peut se rendre dans notre fichier app.component.ts. On crée ensuite une clef avant la déclaration de notre Class et on ajoute TransferState dans notre constructeur :

import {makeStateKey, TransferState} from '@angular/platform-browser';

const IMAGE_KEY = makeStateKey('image');

@Component({
   selector: 'app-root',
   templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
   ...
   constructor(private http: HttpClient,
      private state: TransferState) {
   }
...
}

Ensuite on modifie notre méthode ngOnInit de cette manière :

ngOnInit() {
   const image: any = this.state.get(IMAGE_KEY, null);

   /**
   * Si l'image n'est pac contenue dans notre clef, on effectue la requête
   */
   if (!image) {
      this.http.get('http://www.splashbase.co/api/v1/images/random')
         .subscribe(data =&gt; {
            this.image = data;
            this.state.set(IMAGE_KEY, data as any);
          });
   }

   /**
   * Sinon, on récupère le contenu de notre clef
   */
   else {
      this.image = image;
   }
}

On lance ensuite une build de notre application ainsi que notre serveur :

npm run universal
node server.js

Désormais, le contenu de l’image est transféré du serveur au client et la requête n’est effectuée qu’une fois !

Conclusion

Vous avez maintenant toutes les cartes en mains pour démarrer une application Angular avec le rendu côté serveur configuré.

Il suffit maintenant de faire attention à ne pas appeler des objets disponibles uniquement sur le navigateur (comme window par exemple) sans condition.

Par exemple pour vérifier que l’on est côté client ou non :

import { PLATFORM_ID, Inject } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';

   constructor(
      @Inject(PLATFORM_ID) private platformId: Object,
      @Inject(APP_ID) private appId: string) {
      if (isPlatformBrowser(platformId)) {
         console.log('Je suis appelé côté client !')
      }
    }

Toutes ces astuces simplifieront vos développements Angular avec tous les avantages du rendu côté serveur !

Revue de presse Inno #7

Mobile

Protocoles génériques et Type Erasure en Swift

Avec Swift, vous pouvez définir des protocoles en leur associant un ou plusieurs types génériques. Ces types sont définis en utilisant le mot-clé « associatedtype ».  L’appellation « type générique » est un peu usurpée ici, nous devrions plutôt parler d’un espace réservé pour un type inconnu. En effet, nous verrons que de tels protocoles n’offrent pas une grande souplesse d’utilisation lorsqu’il s’agit de réellement les considérer comme génériques.
En savoir plus :

Développement Web

Django 2.0 Release Candidate désormais disponible

Par Kévin Barralon

Le framework Django dont la prochaine version 2.0 est prévue autour du 1er décembre vient de publier sa version Candidate ce jeudi 15 novembre. Contrairement à ce que l’on pourrait penser, cette nouvelle version ne va pas apporter d’incompatibilités majeures au sein du framework. Les changements seront donc du même acabit que les versions précédentes.

Cependant, le changement important de cette version 2 sera l’incompatibilité avec Python 2.7, dont la fin du support est programmée pour 2020. Django 2.0 supportera donc au minimum la version 3.4, même s’il est chaudement recommandé de passer directement à la dernière version de Python (3.6 actuellement).

Routage d’URL

Au niveau des nouveautés, la nouvelle fonction django.urls.path() rend la syntaxe du routage des URL beaucoup plus simple et lisible. Ainsi, au lieu d’écrire : url(r'^articles/(?P[0-9]{4})/$', views.year_archive)

vous pourrez écrire : path('articles/<int:year>/', views.year_archive)

Cette nouvelle syntaxe permettra également de recevoir dans la vue (views) les arguments avec le typage défini (un nombre entier dans le cas de year au lieu d’une string).

Dans cet exemple, il n’y a toutefois pas de possibilité d’ajouter une contrainte (une année à 4 chiffres dans notre exemple). Pour cela, la fonction actuelle django.conf.urls.url() sera remplacée par django.urls.re_path(), qui permettra de conserver la possibilité de mettre des expressions régulières dans la définition de l’URL.

La fonction django.conf.urls.include() sera également directement disponible via django.urls. Pour pourrez ainsi importer vos modules de la manière suivante from django.urls import include, path.

Autres nouveautés

  • Pour les autres nouveautés : L’admin de Django 2.0 sera désormais responsive, donc adapté aux appareils mobiles.
  • Une nouvelle classe Window a été ajoutée afin de permettre l’utilisation du mot-clé OVER dans les requêtes SQL.
  • Une liste de tous les ajouts mineurs est disponible dans le communiqué officiel.
En savoir plus :

Déployer des services entiers avec Docker Swarm et Gitlab CI

Chez Savoir-faire Linux, je travaille (entre autres) sur l’infrastructure de déploiement pour plusieurs services que l’on héberge, et je suis toujours à l’affût de méthodes innovantes pour améliorer notre pratique DevOps. Présentement, le système de déploiement est axé autour de l’utilisation de Ansible pour « provisioner » un service dans une machine virtuelle, et l’ajuster au besoin après. Mais pour améliorer la stabilité de nos builds, de déploiements et l’agilité avec laquelle on peut faire des déploiements en continu, nous regardons d’autres approches DevOps, comme l’utilisation des containeurs Docker hébergés dans un Registry et déployés par un outil comme Gitlab CI.
Parmi les outils disponibles pour déployer une architecture de « microservice » (créée avec docker-compose), nous trouvons Docker Swarm. En utilisant un certain nombre de serveurs proprement configuré, on peut déployer un « stack » de containeurs avec un simple docker stack deploy. Docker va choisir par la suite la meilleure configuration pour le déploiement des différents containeurs à travers l’infrastructure du Swarm. Il va même aller jusqu’à configurer la réseautique entre les containeurs automatiquement, comme si tu utilisais docker-compose sur un ordinateur en local.
 
La meilleure partie, c’est le fait que ça marche bien avec notre système d’automatisation des builds déjà existant, GitLab CI. Nous pouvons faire le pipeline « build – test – release – deploy » à travers toute notre infrastructure avec GitLab CI et le GitLab Container Registry. Il y a toujours des parties casse-têtes à régler, mais ce système représente déjà un grand bond vers l’avant pour la simplicité et l’efficacité de notre pratique DevOps.
En savoir plus :

Revue de presse Inno #5

Développement Web

Node.js publie la branche 8.x en LTS

Le calendrier de publication de Node.js planifie des mises à jour sur le support à long terme (LTS) chaque octobre normalement, et cette année ne fera pas d’exception. Node.js offre aux développeurs un joyeux cadeau d’Halloween cette année en qualifiant sa version actuelle (8.x) comme une version LTS stable. Cela signifie que les fonctionnalités qui ont été à la fine pointe du développement depuis le début de l’année 2016 ont finalement été rendues disponibles aux utilisateurs qui ont besoin de l’environnement stable et bien testé qui leur est offert par une version LTS.
 

Les nouvelles fonctionnalités très attendues de Node.js 8.x incluent le support au complet pour async / await dans le noyau même de Node.js, des mises à jour au moteur V8, une implémentation HTTP / 2, une nouvelle version de NPM qui permet le versionnage des paquets par épinglage avec les lockfiles, et bien plus encore.

Pour en savoir plus :

Mobile

Firebase Dev Summit

Le Dev Summit de Firebase vient de se terminer et plusieurs annonces ont été faites:
 
Suite au rachat de Fabric par Google, Crashlytics va être intégré à la console Firebase. Ce nouveau système de remontée de crash bénéficiera d’accès aux autres services de Firebase, notamment aux Cloud Functions; ce sont des fonctions (lambdas) déclenchées sur la base de trigger interne à Firebase ou externe par le biais d’une API REST.
L’avantage ici sera de pouvoir déclencher une Cloud Function en réponse à certains crashs remontés. Un crash dans le flow principal d’utilisation de l’app pourrait déclencher l’envoi d’un email à toute l’équipe pour accélérer sa résolution. Une CloudFunction pourrait également se charger de créer une demande sur un outil de gestion.  

Google met le machine learning à l’oeuvre avec un nouveau service, Predictions permettant d’identifier des groupes d’utilisateurs en se basant sur leurs utilisation de l’application. Cela permet ensuite via Firebase de proposer à ces groupes des offres ou des fonctionnalités exclusives afin de conserver leur engagement.
Pour les autres annonces c’est par ici: 

Revue de presse Inno #1

Mobilité

Kotlin : Faster Lazy for Android

Par Loïc Siret

L’utilisation de Lazy en Kotlin permet de déclarer une Property sans l’initialiser immédiatement : Elle le sera lors de son premier usage ! Particulièrement utile lorsque que l’on veut mapper une Property sur le résultat d’un appel à une base de donnée par exemple.

iOS : Présentation de Weavy au CocoaHeads Meetup du 21 septembre dernier

Par Thibault Wittemberg (conférencier)

Dans le monde réel, le tissage implique l’utilisation d’un métier à tisser pour entrelacer deux ensembles de fils à angle : le “Warp” qui s’étend verticalement et le “Weft” qui la traverse horizontalement. Dans cette présentation, nous avons démontré qu’une technique aussi ancienne peut être très utile, notamment lors de la navigation dans une application iOS. L’objectif est de se débarrasser des limitations inhérentes aux “segues” ou au code technique de modèles de conception comme “Coordinator”.

Weavy est un framework open source, basé sur un tel modèle de tissage, qui favorise la programmation réactive, la navigation déclarative, l’injection de dépendance et la séparation des préoccupations.

Développement Web

Intégration de React dans Drupal Core

Par Alexandre Lision

Des discussions ont été entamées à la DrupalCon Vienna pour intégrer React dans Drupal Core. Pourquoi cette discussion maintenant ? Car React a beaucoup plus de traction que d’autres framework JS, et s’est démocratisé. De plus le récent retournement de veste sur la nouvelle licence de React sous MIT va dans la bonne direction pour considérer son intégration dans Drupal. Toutefois, le manque d’expertise JS au sein de l’équipe de contributeurs Drupal pourraient être un bloquant.
Le mix entre Drupal et React native permettrait de bénéficier d’un CMS démocratisé et robuste avec une solution Front-end moderne.

Actualités diverses

Après-midi Contribution, vendredi 29 septembre

L’après-midi Contribution est un événement récurent organisé par le département Innovation digitale, Web et mobilité de Savoir-faire Linux. Il permet à nos consultants de consacrer une partie de leur temps à contribuer à des projets open-source ainsi qu’à se former sur de nouvelles technologies.

Découverte d’un module Python de reconnaissance optique de caractères (OCR)

Par Kevin Barralon

Tesseract est moteur de reconnaissance optique de caractères (OCR) qui reconnaît plus de 100 langues. Il existe un module Python permettant d’utiliser le moteur en important le paquet. Le paquet reconnaît les formats jpeg, png, gif, bmp, tiff, et d’autres grâce au paquet PIL (ou Pillow). Une après-midi a été dédiée à la découverte du paquet et à son installation dans un conteneur Docker dans le but de l’utiliser conjointement avec le micro-framework Python Flask et de créer une API Rest avec notamment un endpoint qui permettrait de renvoyer les résultats de la reconnaissance des caractères d’une image soumise via l’API.

Les demandes de permission inexpliquées des applications Android doivent-elles nous inquiéter?

Capture d'écran (Scrabble)J’ai plus de 120 applications installées sur mon téléphone intelligent. Oui, je sais, c’est beaucoup, d’autant que certaines disposent d’une foule de permissions. Régulièrement, mon système d’exploitation mobile m’informe que l’une d’entre elles n’en a pas encore assez. Il lui en faut plus, mais l’éditeur ne dit pas pourquoi. À première vue, cela me semble dangereux, mais qu’en est-il vraiment?

Pour le savoir, j’ai discuté cette semaine avec Émeric Vigier et Alexandre Lision, deux ingénieurs logiciels de Savoir-faire Linux impliqués dans plusieurs projets d’applications mobiles, dont SFLphone pour Android, actuellement en phase bêta.


Christian – Récemment, j’ai envoyé un courriel au développeur d’un jeu de Scrabble dont la mise à jour réclamait cette nouvelle permission : « Accès aux images, vidéos et fichiers audio stockés sur l’appareil, ainsi que sur un support de stockage externe. » Je voulais savoir pourquoi. Il m’a répondu que « le systeme Android ne permet pas un contrôle très fin des permissions. La seule action potentielle visée par cette permission consiste à enregistrer (par un appui long sur le bouton « Mélanger ») une capture d’écran qui peut m’être envoyée par mail à des fins de débogage. » Puis-je le croire sur parole? Et pourquoi ne pas l’expliquer clairement dès le départ?

Émeric VigierÉmeric Vigier – C’est une réponse sensée. Aujourd’hui, la plupart des applications mobiles demandent également l’accès aux photos et au système de fichiers afin de pouvoir changer un avatar, créer un fond d’écran, etc. S’il s’agit d’une application en laquelle tu avais confiance auparavant et qui a bien fonctionné jusqu’ici, la nouvelle autorisation correspond probablement à l’ajout d’une fonctionnalité.

Aurais-tu des exemples d’applications qui t’ont trahi ou qui ont vendu des photos de nus présentes sur ton téléphone? (rires) Les applications d’ordinateur n’ont pas besoin d’autorisation pour accéder à ces données et personne ne trouve cela inacceptable.

Alexandre LisionAlexandre LisionJe suis d’accord avec Émeric. Les nouvelles autorisations ne sont pas forcément injustifiées et correspondent souvent à l’ajout de fonctionnalités. Le NFC ou la nouvelle génération de composants Bluetooth Low Energy, par exemple, offrent de nouvelles possibilités qui se traduisent par de nouvelles fonctionnalités et, donc, de nouvelles permissions. Google a le mérite de lister clairement à l’utilisateur la liste des autorisations avant le téléchargement. Et puis les permissions ont été grandement affinées, regarde la liste.

Alors, certes, il est toujours possible qu’une permission soit détournée de son usage premier, mais si tu pars de ce principe, tu ne fais plus grand chose avec ton téléphone. Les permissions pourraient être encore plus affinées (par exemple ne donner accès qu’à un dossier de photo spécifique au lieu de tous) mais cela alourdirait considérablement la configuration d’une application. Et la liste de permissions ressemblerait aux conditions d’utilisations d’iTunes, que personne ne lit ou à peu près.

ChristianD’accord. Reste qu’une saine transparence de la part des développeurs pourrait s’inscrire parmi les bonnes pratiques de l’industrie, non? Si les développeurs prenaient la peine d’informer le public des objectifs précis visés par chaque permission, ils informeraient et éduquerait le public qui, actuellement, ne s’en soucie guère. Cette divulgation constituerait aussi un engagement explicite de leur part de ne pas dépasser un périmètre d’action donné. Cela permettrait à des geeks, des médias ou des associations de vérifier qu’ils sont effectivement de bonne foi. En cas d’activité non documentée, le public finirait par le savoir. Bref, cette communication ouverte permettrait de maintenir un lien bidirectionnel de confiance et d’imputabilité entre les deux parties.

Émeric – C’est un vœu pieu, mais à mon avis idéaliste. Rien n’empêcherait un hacker de programmer une application réalisant une fonction de retouche d’image et documentant le fait qu’il a besoin d’accéder à tes images pour le faire. Tu l’accepterais et, en arrière-plan, l’application ferait de la reconnaissance d’image sur tes photos pour potentiellement reconnaître (feu) Oussama Ben Laden et transmettre l’info au gouvernement américain. Aucune divulgation volontaire ne pourrait empêcher les applications frauduleuses.

AlexandreIl faut quand même noter que Facebook s’est lancé dans l’explication de chacune des permissions que son application Android demande. Je n’ai pas d’autre exemple en tête, mais je sais que certains développeurs Android donnent la raison des permissions requises par leur application sur le Play Store. Au final, l’utilisateur devient quand même responsable à partir du moment où il clique sur le bouton « Accepter ». C’est à lui d’évaluer les risques qu’il est prêt a prendre.

En cas d’abus, un utilisateur geek aura évidemment plus de chance de tirer la sonnette d’alarme et de propager l’info. De nombreux outils permettent de vérifier le fonctionnement d’une application – wireshark pour la capture du traffic réseau, android debug bridge pour afficher la console d’événement du téléphone dans un terminal, etc. Les moins geeks auront intérêt à n’installer que des applications bien notées dans le Play Store ou provenant d’une source sûre. Il est en revanche beaucoup plus dangereux d’installer une application téléchargée sur un site inconnu et recommandée par personne, car il est peu probable qu’elle soit passée par un quelconque processus de validation.

ChristianÀ cet égard, est-ce que les utilisateurs de iPhone sont mieux protégés que ceux d’Android?

Émeric – Les dernières versions d’Android sont beaucoup mieux protégés que les précédentes. Le problème, c’est que très peu d’utilisateurs ont la dernière version, car le travail de mise à jour est dévolu au manufacturier de l’appareil et que celui-ci ne fournit que rarement cet effort lorsqu’il s’agit de téléphones bon marché.

Avec iOS, c’est différent. Apple fournit le matériel ET le logiciel. Ils ont infiniment moins de modèles différents à maintenir. C’est ainsi que Tim Cook peut se vanter que 90 % des utilisateurs d’iPhone ont la dernière version. Et c’est en ce sens qu’ils sont mieux protégés que les possesseurs d’Android.

D’un autre côté, le modèle « Google et Apple contrôlent tout » n’est pas mieux. Il faut bien comprendre que dans tous les cas, même si tu n’installes aucune application, tes données personnelles seront quand même accessibles par le constructeur (Apple, Samsung, etc.), donc par un certain nombre d’employés, de partenaires ou d’organisations. [NDLR: voir à ce sujet les conjectures récentes de Jonathan Zdziarski sur iOs]

Le dernier paragraphe de cet article propose que les utilisateurs d’Android puissent activer ou désactiver chacune des permissions de leurs applications. Cela donnerait pour sûr du travail aux développeurs qui devraient s’assurer que la leur fonctionne dans de nombreuses configurations différentes. Mais cela pourrait répondre efficacement à tes craintes.

AlexandreIl faut aussi tenir compte des réactions humaines. Avec Apple, tu ne découvres pas les permissions requises lors de l’installation de l’application, mais pendant son utilisation. Tu peux alors en refuser certaines, mais le fait est que l’utilisateur est mis devant le fait accompli, ce qui peut avoir un effet plus pernicieux. Au lieu de s’interroger sur la logique de l’application ou sur la crédibilité du développeur, on va souvent se dire&nbsp: « Bah! À quoi bon m’inquiéter maintenant alors que je ne suis plus qu’à un clic de ce que je veux faire! ».

Mais, comme l’indique Émeric, Apple a démontré que l’on peut utiliser une application de façon partielle, tant et aussi longtemps que les permissions ne sont pas interdépendantes. Android adopte d’ailleurs également ce système sur certains points sensibles, comme la géolocalisation ou l’activation du Bluetooth, par exemple.

Émeric – Blackberry OS 10 (BB10) a un fonctionnement similaire : l’utilisateur peut activer et désactiver les autorisations de chaque application de manière précise. Evidemment, s’il désactive toutes les autorisations requises, il y a peu de chance que l’application fonctionne correctement. Quant à Firefox OS, je n’ai pas encore eu l’occasion de le manipuler mais j’ai l’impression, d’après ce que je vois ici, qu’il a un fonctionnement plus proche d’Android sur ce
point.

  • Dans la société hyperconnectée d’aujourd’hui, sans voir le mal partout ni renoncer au téléphone intelligent, il est préférable d’être conscient des risques qui l’accompagnent et de les maîtriser.
  • Ainsi, tout effort visant à mieux informer le public, à l’éduquer aux aspects techniques de la mobilité numérique et à lui donner plus de contrôle sur les options de confidentialité représente, à mon avis, un pas dans la bonne direction.
  • Même si cela complique les choses en fragmentant l’écosystème, le fait d’avoir le choix entre plusieurs plate-formes permet de choisir en connaissance de cause celle dont l’approche nous convient le mieux.