Bonjour à tous,
En train de construire un petit site web pour vendre de la musique en ligne, je suis confronté à un problème.
Tout d'abord, les contraintes:
- site multi-plateforme et multi-os (Apache/IIS, Linux/Windows);
- pas de cookie utilisateur.
Les fichiers musicaux vendus sont situés dans un répertoire fichiers/, répertoire étant protégé (-Indexes, deny from all) pour éviter le téléchargement direct, bien évidemment.
La procédure désirée est la suivante:
1. Un client (ayant déjà payé) va sur le site, rentre ses identifiants dans une page html.
2.Cette page redirige vers une page php qui va, selon les identifiants rentrés, afficher une liste des fichiers situés dans le répertoire fichiers/ accessibles au téléchargement. Cette liste est un ensemble de liens <[a]>.
3. Le client clique sur l'un des liens pour télécharger le fichier. Comme le répertoire fichiers/ est protégé, le téléchargement ne marche pas.
4. J'ai eu l'idée alors de changer la cible des liens <[a]> vers une autre page (push.php) qui selon un paramètre passé dans l'URL dans l'attribut href (méthode GET), va chercher le fichier musical en question et l'envoie vers le navigateur (via la fonction header(), en utilisant Content-Disposition) qui n'a alors plus qu'à le sauvegarder. Comme push.php est situé sur le serveur, il a librement le droit de lire les fichiers musicaux situés dans l'emplacement protégé.
Le problème, c'est que push.php n'est pas protégé en lui-même, donc quelqu'un qui irait directement sur le fichier en passant le bon paramètre dans l'URL pourrait avoir accès aux fichiers. J'ai pensé à une protection qui vérifierait HTTP Referer, mais cela s'usurpe trop facilement.
Quelqu'un aurait-il un début de solution pour moi?
# Bien sûr ...
Posté par eolyte . Évalué à 10.
[^] # Re: Bien sûr ...
Posté par Grégory SCHMITT . Évalué à 1.
# SID
Posté par balzane . Évalué à 6.
Remarques :
- pourquoi rechercher une solution fonctionnant indifféremment sous Apache et IIS ? Si tu cherches à construire un petit site web, et non une solution universelle qui concurrencera iTunes, il me semble indispensable de définir en amont l'environnement de production. Si ton projet doit réellement pouvoir être déployé indifféremment sous Apache et IIS, prends-tu bien en compte les différences entre les deux serveurs ? -Indexes, deny from all sonne pour moi comme une directive Apache... mais je ne connais pas IIS :)
- ta contrainte sur l'absence de cookie utilisateur est-elle justifiée ? Le passage d'un id de session via l'URL, quoique possible, ne me semble pas une solution propre.
- Sous Apache, l'utilisation de mod_rewrite te permettra d'utiliser une URL comme mon_site_de_zik.com/download/mon_fichier.mp3, plus propre que mon_site_de_zik.com/push.php?file=mon_fichier.mp3
- que se passe-t-il si l'utilisateur modifie l'URL à la main, genre push.php?file=index.php ?
- enfin, un conseil, révise le chapitre sessions de la doc php :)
[^] # Re: SID
Posté par Grégory SCHMITT . Évalué à 1.
- je développe sur mon ordi (Linux, Apache), mais le serveur de production est lui en Windows/IIS. Je peux cependant répliquer les fonctionnalités .htaccess avec d'autres commandes.
- oui, pas de cookie pour éviter les problèmes de sécurité et pour éviter d'alourdir le tout.
- pas de mod_apache possible, donc non.
- il peut accécder à d'autres fichiers sans en avoir l'autorisation (mon problème!)
- PAS DE COOKIE !
[^] # Re: SID
Posté par balzane . Évalué à 4.
Deux solutions qui peuvent être combinées :
- la valeur de ta variable (le nom du fichier téléchargé) doit correspondre à un motif de regex tel que, par exemple, tout premier caractère soit une lettre ou un chiffre et les derniers caractères .ogg
- la valeur de ta variable doit également être un nom de fichier musical enregistré dans la table correspondante de la BDD
PAS DE COOKIE !
Oui, j'ai bien compris, encore qu'à cette heure j'en grignoterai bien un. Le message que j'ai essayé de faire passer, c''est qu'en php, il existe de méthodes de propagation d'un id de session :
- première méthode, celle interdite : un cookie sur le poste client
- seconde méthode, ma proposition dans mon poste précédent : l'id est propagé via la constante SID, tous tes liens internes deviennent : href="mon_lien.php?sessionid=mon_id_de_session_kinépadanzincookie"
[^] # Re: SID
Posté par Grégory SCHMITT . Évalué à 2.
C'est sur quoi je m'oriente, cela me semble plus propre, même si la sécurité de ce genre de système n'est pas des plus élevée (bien que dans mon cas, au regard de la popularité du site client, cela ne posera vraisemblablement pas de problème). Je pense insérer un code unique dans chaque lien qui sera vérifié par push.php.
[^] # Re: SID
Posté par Ymage . Évalué à 5.
Globalement, que reproches-tu à la sécurité des cookies ?
Et puis, je ne saisis pas non plus de quelle lourdeur tu parles en utilisant des cookies ?
A lire ce sujet, j'ai l'étrange sensation que tu as de nombreux préjugers sur des choix techniques à la base de nombreuses applications Web y compris commerciales, certaines ont des failles d'autres pas, mais je doute que ce soit lié à l'usage ou non de cookies.
Quant à la sécurité que tu prétends vouloir meilleure que dans les applications existantes, je pense que réinventer la roue à ta sauce en évitant de t'inspirer de solutions dont les auteurs se sont déjà confrontés à ce problème est une hérésie.
En me relisant, je constate que je ne t'apporte aucune réponse si ce n'est celle de t'inciter à remettre en question tes idées reçues sur les solutions techniques que tu décries (du verbe décrier) et les produits dont tu pourrais t'inspirer.
Si vous n'aimez pas ce commentaire c'est qu'il est ironique.
[^] # Re: SID
Posté par Grégory SCHMITT . Évalué à 1.
Enfin, pour les solutions déjà existantes, c'est non. Trop de fonctionnalités, trop de choses à maintenir, des potentialités de failles... d'autant plus qu'une partie de la maintenance sera faite par mon client (un ami) qui n'y connaît pas grand-chose et auquel je dois tout expliquer, donc je dois garder ça au plus simple possible.
[^] # Re: SID
Posté par Ymage . Évalué à 5.
Je ne vois pas en quoi l'usage de SID dans l'URL avec des GET et des POST est plus fiable qu'un cookie, sachant que c'est bien plus simple à forger pour les utilisateurs lambda.
Ton cadre technique restant suffisamment flou, il est vrai qu'il sera difficile de te contredire sur ton choix.
A noter que la gestion des sessions/cookie en PHP est, pour ainsi dire, native contrairement à l'usine à gaz de la voie que tu sembles prendre et considérer comme simple.
Enfin, sur les solutions existantes, si tu as lu en détail, je parlais de t'en inspirer pour ne pas réinventer la roue alors que ces patterns ont sûrement déjà été traités par d'autres mais c'est vrai qu'il est toujours plus simple de considérer que notre propre cas ne rentre pas dans les cases et nécessite donc une solution bien spécifique.
L'avantage d'une telle décision étant de pouvoir toujours innover y compris dans les failles de sécurité desquelles tu tiens tant à te préserver :-)
Il y'a au moins un point positif, tu te seras fait la main sur une application non critique et tu apprendras de tes erreurs.
Bon courage à ton client et ami.
Si vous n'aimez pas ce commentaire c'est qu'il est ironique.
[^] # Re: SID
Posté par fearan . Évalué à 3.
Il ne faut pas décorner les boeufs avant d'avoir semé le vent
[^] # Re: SID
Posté par Grégory SCHMITT . Évalué à 2.
En fait, j'ai bien résolu le problème grâce à une identification en deux étapes (identification + vérification au début du téléchargement), et c'est vraiment bien plus léger que de s'occuper d'un cookie, qui présente certes bien plus de fonctionnalités, mais assez inutiles dans mon cas.
Pour le cadre technique, sans donner trop de précision, certains acheteurs vont être amenés à posséder plusieurs comptes, et je sais déjà que certains vont s'emmeler les pinceaux et que leur navigateur (IE6 pour ne pas le nommer) va retenir des cookies valides pour une ancienne session (bref, problèmes en vue).
Pour les solutions existantes, c'est vraiment non. Je ne pense pas pouvoir maîtriser ce code étranger assez vite, et pour mon ami, je dois garder ça le plus simple possible. Crois-moi, c'est vraiment la meilleure solution pour lui.
Et pour mes propres failles, à l'heure actuelle, je n'en vois plus qu'une: un mot de passe est transmis en clair d'une page à l'autre, il faut que je trouve le moyen pour ne transférer que la signature MD5 et ce sera bon. J'ai isolé tous les champs utilisateurs pour éviter les injections PHP. Les mots de passe sont générés aléatoirement, et en l'absence de cookie, une session n'est pas usurpable par un autre. L'avantage de la simplicité !
[^] # Re: SID
Posté par NeoX . Évalué à 2.
- avoir une durée de vie limitée (1h ?)
- etre effacer quand la personne clique sur "logout"
[^] # Re: SID
Posté par GG (site web personnel) . Évalué à 3.
C'est vraiment rare pour certaines personnes, pour la plupart, surtout si elles sont sur leur ordinateur personnel.
Je ne sais pas si on peut limiter la durée de vie d'un cookie à une session. C'est possible (sans que cela dépende de la configuration du navigateur).
A bientôt
Grégoire
Pourquoi bloquer la publicité et les traqueurs : https://greboca.com/Pourquoi-bloquer-la-publicite-et-les-traqueurs.html
[^] # Re: SID
Posté par balzane . Évalué à 3.
[^] # Re: SID
Posté par benoar . Évalué à 2.
[^] # Re: SID
Posté par leviathan (site web personnel) . Évalué à 3.
J'aimerais bien savoir en quoi c'est plus léger qu'un :
if (isset($_SESSION['login']) && $_SESSION['login'] === true) { }
De plus tu peux très bien utiliser les sessions sans cookies en passant le SID dans l'URL et en forçant l'utilisation du SID en paramètre (en fixant session.use_cookies à 0, session.use_only_cookies à 0 et session.use_trans_sid à 1 via la fonction ini_set())
Ce code fonctionne parfaitement sans acceptation des cookies par le client (et en plus il ajoute automatiquement le SID dans l'URL
ini_set('session.use_cookies', 0);
ini_set('session.use_only_cookies', 0);
ini_set('session.use_trans_sid', 1);
session_start();
if (isset($_SESSION['id']) === false) {
echo 'pas de session';
$_SESSION['id'] = 42;
} else {
echo $_SESSION['id'];
$_SESSION['id'] = 1;
}
<a href='./test.php>lien
Enfin pour finir avec les sessions, si tu initialise bien ta session lors d'une connexion, tu n'auras aucun problème de cache et tes utilisateurs pourront se connecter avec plusieurs login sans que cela ne pose de problème.
Au moins avec cette solution, pour peu que tu sécurises un peu la session, tu n'auras plus de problème avec l'identification.
Ensuite, pour les fichiers que l'utilisateur peut télécharger, il suffit de les garder en session pour vérification avant d'envoyer le fichier demandé avec ta page php
ini_set('session.use_cookies', 0);
ini_set('session.use_only_cookies', 0);
ini_set('session.use_trans_sid', 1);
session_start();
// Dans la page de login
// Si le login est réussi
// on stocke les fichiers autorise
// dans la session
if ($login === true) {
$files = file_get_contents('./fichier_pour_l_utilisateur_hors_repertoire_web_avec_fichier_autorise');
$_SESSION['files'] = explode(';', $files);
$_SESSION['login'] = true;
} else {
unset($_SESSION['files']);
unset($_SESSION['login']);
}
// Dans la page de telechargement
// On vérifie que l'utilisateur est connecté
if (isset($_SESSION['login']) === false || $_SESSION['login'] !== true) {
// l'utilisateur n'est pas connecté
// on le renvoie sur la page de login
header('Location: login.php');
exit();
} else {
// l'utilisateur est connecté
// on vérifie que le fichier demandé
// fait parti des fichiers autorisés
if (in_array($_GET['music'], $_SESSION['files']) === true) {
// le fichier est bin, on l'envoie
// code d'envoie du fichier avec les headers
} else {
// le fichier ne fait pas parti de la liste
// on l'indique à l'utilisateur
echo 'fichier interdit....';
}
}
[^] # Re: SID
Posté par Ymage . Évalué à 2.
Allez, on y croit ... ça va marcher...
Si vous n'aimez pas ce commentaire c'est qu'il est ironique.
[^] # Re: SID
Posté par benoar . Évalué à 4.
il faut que je trouve le moyen pour ne transférer que la signature MD5 et ce sera bon
Une replay attack, ça te dit quelques chose ? Faire la sécurité soit même et croire que c'est bon parce qu'"on" a pensé à tout, c'est un mauvais départ ...
# Impossible
Posté par dyno partouzeur de drouate . Évalué à 6.
Le mieux que tu pourras faire, c'est probablement générer des liens jetables, qu'on ne pourra cliquer qu'une fois, par exemple en créant un id de lien unique (et pas facilement devinable) quand tu génères la liste des fichiers et en les enregistrant dans une base mysql : quand on appelle push,php avec le bon id, ça supprime le lien de la bdd et ça envoie le fichier.
Tu peux éventuellement également empêcher quelqu'un de cliquer sur le lien si son IP n'est pas celle de celui qui a généré la liste, mais cela risque d'interférer avec l'utilisation d'un proxy.
[^] # Re: Impossible
Posté par Krunch (site web personnel) . Évalué à 3.
pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.
[^] # Re: Impossible
Posté par Grégory SCHMITT . Évalué à 3.
Pour les liens temporaires, j'y avais pensé, malheureusement, étant limité par la plate-forme de production (pas de liens symboliques, pas de module spécifique à Apache), j'avais abandonné l'idée. Il faudra vraisemblablement que je creuse l'idée.
# php/mysql login/password
Posté par NeoX . Évalué à 5.
et un liste d'ID autorisé/autorisant le telechargement ?
1°) l'utilisateur d'identifie (on verifie qu'il a un compte)
2°) on recupere la liste des fichiers auquels il peut pretendre
(table contenant des couples id_client, id_morceau)
3°) tu generes une page contenant cette liste avec les liens qui vont bien
4°) dans le lien tu reverifies son login/pass (methode get, sessionid...)
bref tu utilises les fonctionnalités de gestion de session que propose apache/php
5°) avantage de ce systeme ?
un morceau peut-etre mis à disposition de plusieurs clients
[^] # Re: php/mysql login/password
Posté par Grégory SCHMITT . Évalué à 2.
[^] # Re: php/mysql login/password
Posté par NeoX . Évalué à 4.
1°) login => OK => generation d'une valeur aleatoire pour cette session
2°) cette valeur est passée dans toutes les pages d'apres car c'est elle qui va faire que le lien login/pass et droit d'acces
=> pas de cookies (bien que ce soit fait pour ca)
=> tu t'assures que l'utilisateur de la page precedente est bien identifié
mais il me semble que les sessions PHP n'ont pas besoin de cookies pour fonctionner
[^] # Re: php/mysql login/password
Posté par Grégory SCHMITT . Évalué à 2.
Hélas, si (en tout cas, c'est le cas chez moi).
Globalement, j'ai ajouté un paramètre GET supplémentaire dans l'URL qui permet d'authentifier un tant soi peu le téléchargement.
# pourquoi réinventer la roue?
Posté par GG (site web personnel) . Évalué à 1.
la plupart des logiciels de vente en ligne le font (et d'autres choses).
Alors, il te suffit d'installer ces logiciels; de les tester, et de garder celui qui te plaît le mieux.
Ensuite, tu adaptes la charte graphique à ton image et voilà.
A bientôt
Grégoire
Pourquoi bloquer la publicité et les traqueurs : https://greboca.com/Pourquoi-bloquer-la-publicite-et-les-traqueurs.html
[^] # Re: pourquoi réinventer la roue?
Posté par Grégory SCHMITT . Évalué à 3.
[^] # Re: pourquoi réinventer la roue?
Posté par Kerro . Évalué à 4.
Notes tout de même qu'elles ont un avantage par rapport à ta solution: ça fonctionne.
C'est un tout petit avantage, mais bon des fois c'est suffisant.
[^] # Re: pourquoi réinventer la roue?
Posté par GG (site web personnel) . Évalué à 3.
C'est sur que si tu ne regardes que OScommerce 1, tu peux être déçu.
Il n'y a pas que OScommerce... tiens, tu peux regarder la qualité du code source de Thelia, et il existe même un plugin pour Spip pour que Spip s'interface à Thélia.
Oui, si c'est pas libre, même pas la peine d'en parler, mais visiblement tu n'a pas essayé les solutions libres existantes.
J'attends de voir ce que tu ferras, ça donnera un code HTML propre, et 100% valide, sans aucune faille de sécurité.
Bonne soirée.
Grégoire
Pourquoi bloquer la publicité et les traqueurs : https://greboca.com/Pourquoi-bloquer-la-publicite-et-les-traqueurs.html
[^] # Re: pourquoi réinventer la roue?
Posté par Grégory SCHMITT . Évalué à 2.
[^] # Re: pourquoi réinventer la roue?
Posté par GG (site web personnel) . Évalué à 3.
Bonjour,
est ce que tu va utiliser un autre système de base de donnée? genre sqlite, ou des fichiers simples?
C'est vrai que sans base de donnée, beaucoup de choses sont simplifiées. (installation, migrations, sauvegardes, sécurité...).
A bientôt
Grégoire
Pourquoi bloquer la publicité et les traqueurs : https://greboca.com/Pourquoi-bloquer-la-publicite-et-les-traqueurs.html
[^] # Re: pourquoi réinventer la roue?
Posté par Grégory SCHMITT . Évalué à 2.
[^] # Re: pourquoi réinventer la roue?
Posté par Ymage . Évalué à 5.
Si vous n'aimez pas ce commentaire c'est qu'il est ironique.
# Bon, vous avez gagné...
Posté par Grégory SCHMITT . Évalué à 3.
Au moins un avantage de SID, c'est que je pourrai fusionner les sessions anonymes et les utilisateurs enregistrés.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.