IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Android Discussion :

Sécurisation API REST


Sujet :

Android

  1. #1
    Candidat au Club
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mars 2015
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2015
    Messages : 4
    Points : 3
    Points
    3
    Par défaut Sécurisation API REST
    Bonjour,

    Après avoir lus des dizaines de post des 4 coins du monde, je n'ai pas trouvé de réponse claire et complète sur le problème suivant :

    D'un côté j'ai développé un serveur web avec un certain nombre de requêtes en API REST
    De l'autre une appli Android qui va échanger à intervalle régulier avec ce serveur en REST / JSON

    Des 2 côtés je me suis appuyé sur Spring, avec RestTemplate côté Android. La communication se fait correctement.

    Afin de sécuriser les connexions, j'envisage maintenant d'utiliser SSL/TLS, avec pour commencer un certificat serveur autosigné (au moins pour mettre au point la mécanique). Selon diverses "bonnes pratiques" il ne faut pas utiliser de sessions dans ce type d'interface, par contre comment peut-on éviter à chaque requête de redéclencher le handshake SSL ? Faut-il utiliser les cookies ? Ou bien faut-il refaire le handshake à chaque requête quitte à ce que ce soit "lourd" ?

    Quelques lignes de code utilisé en mode "test" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    URL url = new URL(params[0]);
    HttpsURLConnection httpsUrlConnection =  (HttpsURLConnection) url.openConnection();
    SSLContext ctx = SSLContext.getInstance("TLS");
    ctx.init(null, new TrustManager[]{ new AlwaysTrustManager() }, null);
    SSLSocketFactory factory = ctx.getSocketFactory();
    httpsUrlConnection.setSSLSocketFactory(factory);
    httpsUrlConnection.setHostnameVerifier(TRUSTING_HOSTNAME_VERIFIER);
    httpsUrlConnection.setRequestMethod("GET");
    int responseCode = httpsUrlConnection.getResponseCode();

  2. #2
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Je crois que tu confonds "session" et "connexion".

    REST préconise de ne pas avoir de "session" (c'est à dire d'information lié à la session côté serveur). C'est habituellement ainsi que l'authentification est faite: un premier appel à une fonction d'authentification stocke dans la session (coté serveur donc) les informations sur l'utilisateur, évitant à chaque fois de les redemander.
    Comment on fait sous REST donc ? Ben pendant l'authentification initiale (on n'y coupe pas) on place en cookie (ou paramètre), un token d'authentification qui va contenir toutes les informations d'authentification côté serveur. Ce token n'est lisible que par le serveur et que pendant une durée donnée. Le token peut être re-émis à chaque requête (permettant d'étendre la durée d'une authentification). Tant que le client le colle de manière inchangée à chaque requête.

    Mais REST c'est déjà du high-level (au dessus de HTTP/HTTPS)


    Maintenant, à propose de SSL/TLS (au passage SSL possède pas mal de failles de sécurité, il me semble que seul TLS soit "accepté" désormais)... là on parle de la couche de transport (TCP/TLS). Le handshake sera nécessaire à chaque nouvelle connexion sécurisée. Mais HTTP1.1+ permet de conserver ces connexions (en fonction du serveur donc), à condition bien entendu, de réutiliser côté client le même provider de connexions.
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  3. #3
    Candidat au Club
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mars 2015
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2015
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    Merci pour ces précisions,

    Pour l'authent, ok pour le token, je regarderai ça après, c'est effectivement bien la gestion des connexions qui me pose problème.

    Mon serveur (apache + tomcat) est visiblement bien en http 1.1, par contre côté client, en utilisant directement HttpUrlConnection, ça ne fonctionne pas. J'ai ajouté un disconnect comme indiqué dans la doc qui devrait permettre la réutilisation, mais j'ai quand même 2 handshakes pour 2 requêtes consécutives.

    Si des exemples de code sont dispo, je suis preneur de référence.

  4. #4
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Heu, j'ai pas tout suivi, mais si tu rajoutes un "disconnect" la connexion est perdue non ? ça me semble logique...

    Normalement le header "Connection: Keep-Alive" (en HTTP 1.0) devrait suffire à conserver la connexion ouverte pour de futures requêtes.
    En HTTP 1.1 c'est le comportement par défaut.

    Tant que l'ensemble des données du stream ont été lues, depuis Java 1.6, chaque appel à URL.openConnection() va fournir la connexion précédente.
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  5. #5
    Candidat au Club
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mars 2015
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2015
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    Pour le disconnect, c'est la doc qui le dit :
    Disconnect. Once the response body has been read, the HttpURLConnection should be closed by calling disconnect(). Disconnecting releases the resources held by a connection so they may be closed or reused.

    Après divers essais, il semblerait que ce soit mes requêtes Resttemplate pas complètement bien configurées qui perturbent mes requêtes de tests. En isolant mes requêtes de test, j'ai bien la réutilisation qui opère (log serveur apache) :

    AH02034: Initial (No.1) HTTPS request received for child 55

    puis

    AH02034: Subsequent (No.2) HTTPS request received for child 55

    sans nouveau handshake.

    Par contre, bizarrement, j'ai systématiquement une erreur I/O
    OpenSSL: I/O error, 5 bytes expected to read on BIO#69dd58 [mem: 38d85b3]
    Ce qui n'empêche pas la poursuite des opérations.

    Autre comportement étonnant sur Android, le Cipher négocié est :
    Protocol: TLSv1, Cipher: RC4-MD5 (128/128 bits)
    Ce qui ne semble pas terrible, alors que le même code, exécuté dans une servlet de mon serveur web/rest abouti à
    Protocol: TLSv1.2, Cipher: ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)
    Ce qui semble beaucoup mieux

    Pour info mes requetes de tests :
    SSLContext ctx = SSLContext.getInstance("TLSv1");
    ctx.init(null, new TrustManager[]{ new AlwaysTrustManager() }, null);
    SSLSocketFactory factory = ctx.getSocketFactory();


    URL url1 = new URL("https://...monUri1...");
    HttpsURLConnection httpsUrlConnection1 = (HttpsURLConnection) url1.openConnection();
    httpsUrlConnection1.setSSLSocketFactory(factory);
    httpsUrlConnection1.setHostnameVerifier(TRUSTING_HOSTNAME_VERIFIER);
    httpsUrlConnection1.setRequestMethod("GET");
    httpsUrlConnection1.connect();
    InputStreamReader in1 = new InputStreamReader((InputStream) httpsUrlConnection1.getContent());
    httpsUrlConnection1.disconnect();

    URL url2 = new URL("https://...monUri2...");
    HttpsURLConnection httpsUrlConnection1 = (HttpsURLConnection) url1.openConnection();
    httpsUrlConnection1.setSSLSocketFactory(factory);
    httpsUrlConnection1.setHostnameVerifier(TRUSTING_HOSTNAME_VERIFIER);
    httpsUrlConnection1.setRequestMethod("GET");
    httpsUrlConnection1.connect();
    InputStreamReader in2 = new InputStreamReader((InputStream) httpsUrlConnection2.getContent());
    httpsUrlConnection1.disconnect();


    Je vais essayer de reconfigurer la partie Resttemplate pour retrouver le même comportement.

  6. #6
    Candidat au Club
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mars 2015
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2015
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    Au final ça à l'air de fonctionner avec RestTemplate :
    en utilisant une dérivée de SimpleClientHttpRequestFactory + HttpBasicAuthentication

    Le serveur Apache génère un J_SESSION_ID que je réutilise et le handshake est exécuté en version rapide au moins une ou deux fois consécutives

    Pas trouvé le moyen d'utiliser les "session tickets"...

    Je reprendrai ça plus tard, avec une authentification basée sur token.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Sécurisation d'une API REST
    Par yeste64 dans le forum REST
    Réponses: 0
    Dernier message: 05/07/2014, 11h02
  2. [2.x] [Symfony2] Sécurisation API REST, help
    Par nayro57 dans le forum Symfony
    Réponses: 4
    Dernier message: 24/06/2014, 11h03
  3. [Authentification] API REstful PHP
    Par yoshï dans le forum REST
    Réponses: 1
    Dernier message: 22/07/2008, 09h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo