Sécuriser l'envoi de données via une URL

Le problème exposé dans ce sujet a été résolu.

Salut à tous ! :-D

Je suis actuellement en terminale et, dans le cadre de la SI, je dois réaliser un projet. En passant les détails, nous voulons faire une ruche intelligente, c’est-à-dire que la ruche va envoyer des données (températures, humidités et masse) sur un site Web.

La partie électronique se fera sur Arduino. Le site Web sera codé avec le framework Django.

Pour assurer l'échange des données entre le système électronique et le serveur, nous avons pensé à faire transiter les données (en JSON) par une URL comme

1
http://ruche.fr/envoyer/

avec une variable POST contenant

1
2
3
4
5
6
{
    "id": "ruche1",
    "temperature": 22,
    "humidity": 56,
    // ...
}

Ma question donc est de savoir comment on peut sécuriser un tel envoi, de sorte que l’Arduino seul puisse faire la requête.

Comme je vais utiliser le système d'utilisateur de Django, est-il possible de se connecter seulement avec une requête POST (en passant les identifiants en arguments) ? Passer un mot de passe en argument est-il sécurisant ?

Connaissez-vous d’autres moyens ?

Merci beaucoup !
Bonne fin d'année :-)

Bah, si personne n'a accès à l'arduino, tu peux simplement utiliser un token. L'authentification utilisateur/mot de passe de Django est un peu lourde pour ton projet.

Dans Django je suppose que tu as un modèle Ruche. Tu y ajoutes un champ "token" qui est un UUID généré à la création d'une ruche. Puis sur chaque arduino tu ajoutes par exemple une variable d'environement RUCHE_TOKEN. Puis quand l'arduino fait sa requête vers /envoyer, il lit la variable d'environement et ajoute le token au JSON ("token": "..."). Dans ta vue Django "envoyer", tu vérifies que le token correspond à la ruche.

+2 -0

Merci beaucoup victor ! En effet, je n'avais pas pensé à utiliser un token sur chaque ruche, ça permet d'avoir un identifiant unique et sécurisé.

Au fait, je n'ai pas encore codé quoi que ce soit, je préfère me renseigner avant. :-)

Je comptais faire un modèle Ruche avec donc un UUID. Ensuite, de faire un modèle Donnee avec un champ ruche qui indique la ruche via une clé étrangère. Dans ma vue, il faut donc que je vérifie que le token existe et ajouter les données. Mais, est-ce que cette unique vérification suffit ?

Je comptais faire un modèle Ruche avec donc un UUID.

Juste histoire d'être extra-sûr que c'est extra-clair : chaque ruche a de toute façon un identifiant unique, c'est son ID. Et ce que je propose, c'est d'ajouter un champ token qui sera un UUID. ;)

un modèle Donnee avec un champ ruche qui indique la ruche via une clé étrangère.

Yep, très bien.

Dans ma vue, il faut donc que je vérifie que le token existe et ajouter les données.

Il faut surtout vérifier que le token envoyé avec les données par l'arduino correspond bien au token de la ruche pour lequel les données sont envoyées.

Mais, est-ce que cette unique vérification suffit ?

Tout dépend ce contre quoi tu veux te protéger. En l'état et sans TLS (https), il est possible de sniffer le traffic et d'intercepter une des requêtes, puis d'en forger de nouvelles pour faire croire à ton backend Django que les données viennent de l'arduino. En effet, les données (dont le token) transitent en clair. Donc une étape supplémentaire serait d'utiliser TLS.

Ce qui est sûr, c'est que sans TLS, le token n'est ni plus sûr ni moins sûr qu'utiliser une gestion d'utilisateur côté Django et de faire transiter en clair le couple user/password avec tes données…

+1 -0

Oui oui, c'est clair. :-)

Comment pourrais-je vérifier que le token envoyé par l'Arduino est bien le bon ? S'il existe, ça n'empêche pas que ce soit celui de la bonne ruche…

Pour l'histoire de la sécurisation du transfert des données, c'est bien ce que je pensais. Je voudrais éviter que le token soit intercepté. Est-ce qu'il suffit que je paramètre nginx pour utiliser SSL ? Ça marcherait même avec un certificat auto-signé ?

+0 -0

Comment pourrais-je vérifier que le token envoyé par l'Arduino est bien le bon ? S'il existe, ça n'empêche pas que ce soit celui de la bonne ruche…

C'est très facile !

Tes ruches :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
[
  {
    "id": 1,
    "nom": "ruche 1",
    "token": "ae65061e-647f-4404-baed-d911316f4135"
  },
  {
    "id": 2,
    "nom": "ruche 2",
    "token": "e19d508c-1ea5-444f-ba79-e440b12387b7"
  },
  {
    "id": 3,
    "nom": "ruche 3",
    "token": "8b0bfb56-2851-45ff-879e-42c5f143487d"
  }
]

Arduino post 1 :

1
2
3
4
5
6
{
  "nom": "ruche1",
  "token": "ae65061e-647f-4404-baed-d911316f4135",
  "temperature": 22,
  "humidity": 56,
}

Tu vérifies que dans Ruches, "ruche1" a bien "ae65061e-647f-4404-baed-d911316f4135" comme token.

Arduino post 2 :

1
2
3
4
5
6
{
  "nom": "ruche2",
  "token": "ae65061e-647f-4404-baed-d911316f4135",
  "temperature": 12,
  "humidity": 42,
}

Tu vérifies et tu remarques que le token correspond pas à la ruche, donc tu n'enregistres pas.

+1 -0

Allez, en pinaillant, ça serait un tout petit peu mieux si tes ruches postaient sur des URL différentes.

PUT http://ruches.fr/api/ruche2

1
2
3
4
5
{
  "token": "ae65061e-647f-4404-baed-d911316f4135",
  "temperature": 12,
  "humidity": 42,
}

Si tu n'as pas de token dans le contenu de la requête HTTP, tu renvoies une réponse HTTP avec un code d'erreur 401.

Si tu reçois une requête sur /api/ruche1 qui contient un mauvais token tu renvoies une réponse HTTP avec un code d'erreur 403.

Et là tu commences à te rapprocher un peu d'une API REST. Comme ça tu auras appris quelque chose de nouveau :)

+1 -0

J'avais aussi pensé à utiliser une API. Au moins, j'aurais un truc prore. Mais, je me demande si c'est pas un peu overkill. Mais, ce serait une super bonne idée !

Est-ce que pour mon utilisation, il vaudrait mieux que j'utilise un package comme Django REST framework ou que je fasse un truc à la main (vu que ça servirait juste pour ajouter ces données) ?

Le problème des URL différentes, c'est que l'Arduino devra faire plusieurs requêtes. Il est connecté à Internet avec un shield GSM, donc faudrait limiter les requêtes mais pourquoi pas. (À voir le forfait que les profs veulent bien nous acheter.) :-P

+0 -0

Oui c'est overkill.

Maintenant, si tu as du temps et que tu as envie d'apprendre, essaie. C'est comme ça qu'on apprend tout plein de nouveaux trucs (par exemple que tu peux passer le token en tant que header de la requête HTTP), ou pourquoi j'ai plutôt choisi une requête PUT plutôt qu'un POST, …

Si c'est le genre de question sur lesquels tu as envie de passer un peu de temps (et que le protocole HTTP t'intéresse) alors fonce.

+1 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte