web-dev-qa-db-fra.com

Session perdue lors du passage de HTTP à HTTPS dans PHP

Lors de l'envoi de l'utilisateur vers une page de paiement, il passe de http://sitename.com à https://sitename.com.

Par conséquent, $_SESSION les variables sont perdues.

Le site dispose d'un certificat SSL valide qui peut être utile ou non.

62
Allan

Lorsque vous basculez entre les services HTTP et HTTPS sur le même serveur, votre ID de session HTTP n'est pas transmis à la session HTTPS. Vous pouvez le définir en passant l'ID de session de la page HTTP à la page HTTPS de l'une des trois manières possibles:

De PHP: session_start :

session_start() crée une session ou reprend la session actuelle en fonction de l'ID de session en cours qui est transmis via une demande, telle que GET, POST ou un cookie

Lorsque vous utilisez des sessions, vous démarrerez normalement votre script avec session_start(). Si le navigateur a un cookie d'ID de session défini, session_start() utilisera cet ID de session. Si le navigateur n'a pas de cookie d'ID de session défini, session_start() en créera un nouveau.

Si l'ID de session n'est pas défini (dans votre exemple, le navigateur crée un nouveau cookie d'ID de session pour la session HTTPS), vous pouvez le définir à l'aide de la fonction session_id(). session_id() renvoie également commodément l'ID de session sous forme de chaîne. Alors

...

$currentSessionID = session_id();

...

définit le $currentSessionID variable égale à l'ID de session en cours, et

...

session_id($aSessionID);

...

définit le cookie sessionID dans le navigateur sur $aSessionID. de PHP: session_id

Voici un exemple avec deux scripts. L'un est accessible via HTTP et l'autre est accessible via HTTPS. Ils doivent être sur le même serveur pour conserver les données de session.

Script 1 (HTTP) :

<?php

// This script will create a session and display a link to your secure server address
// to transfer your session ID. In this example, the secure page to receive the session
// ID is located at http://www.yoursite.com/safePages/securePage.php

// Start a session using the current session ID stored in a cookie, or create
// a new session if none is set.
session_start();

$currentSessionID = session_id();

// Set a variable that will be retrieved with the HTTPS script.
$_SESSION['testvariable'] = 'It worked';

// $secureServerDomain is the domain of your secure server
$secureServerDomain = 'www.yoursite.com';

// $securePagePath is the path to the page that will receive and set the session ID.
$securePagePath = '/safePages/securePage.php'

echo '<a href="https://' . $secureServerDomain . $securePagePath . '?session="' . $currentSessionID . '">Click here to transfer your session to the secure server</a>';

?>

Script 2 (HTTPS) :

<?php

// Retrieve the session ID as passed via the GET method.
$currentSessionID = $_GET['session'];

// Set a cookie for the session ID.
session_id($currentSessionID);

// Start a session.
session_start();

// Test retrieval of variable set when using HTTP.
if (!empty($_SESSION['testvariable'])) {
      echo $_SESSION['testvariable'];
} else {
      echo 'It did not work.';
}

?>

Pour que cela fonctionne, les serveurs HTTP et HTTPS doivent utiliser le même substrat de stockage de données de session (c'est-à-dire pour le gestionnaire de fichiers par défaut, exécuté sur la même machine physique avec le même php.ini). Il y a quelques failles de sécurité ici, donc je n'utiliserais pas ce code pour transférer des informations sensibles. Il s'agit simplement d'un exemple réalisable.

Lorsque j'ai rencontré ce problème auparavant, j'ai trouvé ce qui précède comme solution rapide, mais je me souviens juste de la cause d'origine du problème. J'allais de http://www.example.com/page.php à https://example.com/page.php (remarquez l'absence de "www "). Assurez-vous que http://www.example.com/page.php sera lié à https://www.example.com/page.php et http://example.com sera lié à https://example.com/page.php .

PS, je n'ai pas réellement exécuté ces scripts, donc il peut y avoir une faute de frappe ou deux qui les empêche de fonctionner correctement tels quels.

69
Jacob

On dirait que le cookie de session est configuré pour être sécurisé. Les cookies ont un indicateur "sécurisé" qui, s'il est défini sur true, signifie que le cookie ne sera pas envoyé à des sites non https. PHP l'utilise probablement pour ses cookies de session. Vous pouvez changer cela avec la fonction session_set_cookie_params , ou avec le paramètre session.cookie_secure dans php.ini.

16
JW.

Nous avons également eu ce problème. Il s’est avéré que nous utilisions le correctif suhosin sur notre installation PHP. Nous le corrigeons en définissant suhosin.session.cryptdocroot = Off dans /etc/php.d/suhosin.ini.

Pour le manuel de suhosin sur suhosin.session.cryptdocroot voir http://www.hardened-php.net/suhosin/configuration.html#suhosin.session.cryptdocroot .

Nous avons initialement trouvé le correctif à partir de ce billet de blog: http://www.yireo.com/blog/general-news/315-switch-between-http-and-https-looses-php-session .

12
Tom

La solution suivante suppose que les serveurs sécurisés et non sécurisés ont accès aux mêmes services principaux (cache, magasin de base de données, etc.).

Nous avons dû faire face à ce même problème lors de l'envoi d'un utilisateur à notre flux de paiement lorsqu'ils ont terminé leurs achats. Pour résoudre ce problème, nous avons mis en place une couche de mise en cache et mis en cache toutes les données pertinentes. Par exemple, nous glanerions les identifiants de produit et l'ID utilisateur à partir des valeurs de session, les sérialiserions, créerions un hachage et finalement stockerions les données de session dans le cache en utilisant le hachage comme clé. Nous redirigerions ensuite l'utilisateur vers le site sécurisé avec le hachage dans l'url.

Lorsque l'utilisateur se retrouverait sur le site sécurisé, nous tenterions d'extraire les données du cache en fonction du hachage. Ensuite, avec l'ID utilisateur et les ID produit, nous pourrions charger toutes les données de prix et de description hors de la base de données et les présenter à l'utilisateur pour un examen final de la commande.

Il existe un risque hérité du fait que les données du cache sont volatiles, mais nous n'avons jamais eu de problème avec elles car la redirection se produit rapidement.

6
Mike Purcell

Vous ne pouvez pas transmettre de valeurs de session entre différents domaines. Vous devez utiliser http post-get ou une base de données pour transmettre vos valeurs. Pour des raisons de sécurité, vous pouvez concaténer toutes vos valeurs dans une chaîne et utiliser

sha1($string)

et postez-le à côté de vos valeurs et calculez le sha1 pour les valeurs obtenues sur l'autre page, puis comparez les hachages.

La méthode de publication sur différents domaines fait que les navigateurs affichent un message de sécurité, alors n'utilisez pas cela.

L'utilisation de la méthode url for get n'est pas sûre, vous devrez demander un mot de passe sur la page redirigée pour autoriser les paramètres get dans votre système.

N'utilisez pas de cookies si vous avez besoin de sécurité.

La façon dont je suggère est, enregistrez les valeurs dans une base de données et générez une clé, puis créez votre lien de redirection à l'aide de votre clé, transférez la page des utilisateurs avec un paramètre get qui a la clé, puis l'utilisateur de la page est redirigé vers obtient cette clé , récupère les données et supprime la clé. vous pouvez générer une clé avec sha1

PAGE 1---
$key=sha1($allvalsconcat);
//insert your session values to a database also the key in a column
header("Location: page2.php?key=".$key);

PAGE 2---
// select from database where key=$_GET["key"];
// delete from table where key=$key

c'est assez sûr.

les choses qui peuvent arriver: un script entrant des valeurs aléatoires pour le paramètre "clé" pour que votre site web charge les données dans votre mémoire?

Cela ne se produira pas car vous supprimez l'entrée après l'avoir utilisée. Une idée fausse commune est que les valeurs get ne sont pas sûres et doivent toujours être évitées.

vous pouvez définir le type de moteur de table sur "mémoire" dans mysql si vous voulez la perfection des performances.

1
Uğur Gümüşhan

Pensez à utiliser HTTPS pour toutes les pages, c'est le moyen le plus simple d'éviter ce problème et cela améliorera la sécurité de votre site.

Si SSL pour toutes les pages n'est pas une option pour vous, alors vous pouvez utiliser cette approche: Basculer entre les pages HTTP et HTTPS avec un cookie de session sécurisé . L'idée derrière est que vous laissez le cookie de session non sécurisé (et donc disponible pour les pages HTTP et HTTPS), mais que vous disposez d'un second cookie sécurisé pour gérer l'authentification. C'est un bon moyen de séparer les deux préoccupations "maintien de la session" et "authentification".

1
martinstoeckli

On dirait que votre cookie de session est créé avec l'indicateur sécurisé, mais il y a quelque chose avec l'URL de votre page de paiement en raison de laquelle le cookie de session n'est pas passé.

Ou probablement, votre cookie de session n'est pas sécurisé - juste que l'url de la page de paiement est suffisamment différent ( http://mysite.com vs http://www.mysite.com ) que le navigateur n'envoie pas le cookie.

Si vous souhaitez en savoir plus sur le basculement de http à https et vice versa - jetez un œil à à mon article sur ssl sélectif :-)

1
Raghu

Je recommanderais, en plus de ce que la plupart ont déclaré ici à propos du transfert d'informations chiffrées, de le voir comme si vous transfériez des informations sensibles via une API tierce. Comment savez-vous que quelqu'un n'usurpe pas la demande? Il existe de nombreux protocoles pour vraiment confirmer l'authenticité de la demande, selon la sensibilité de votre configuration. Vous vous ouvrez à des comptes compromis si vous ne faites pas attention.

Même s'il est sur le même serveur, considérez ceci:

Lorsque quelqu'un suit le lien, l'action de formulaire, etc. qui passe sur la clé chiffrée, qu'est-ce qui empêcherait quelqu'un de le renifler AVANT d'accéder à la version sécurisée de votre site? Si j'étais dans un endroit WIFI public, cela ne serait pas trop tiré par les cheveux. Je pourrais prétendre être votre site, rediriger les demandes vers mon propre ordinateur portable, récupérer le jeton et rediriger le visiteur vers son lieu de destination. Ils supposeraient que c'était un problème et n'en auraient aucune idée. Maintenant, je peux me connecter en tant qu'eux, et peut-être aller acheter 10 000 $ de choses avec leur carte de crédit au dossier et l'expédier ailleurs. Le degré de prudence que vous prenez ici doit correspondre au degré de sensibilité.

Assurez-vous également que vous expirez vos jetons (une seule utilisation, après X nombre de secondes, etc.), mais j'envisagerais également d'utiliser le modèle Post-Redirect-Get aux deux extrémités, à savoir:

N'affichez pas le lien direct sur une page ou sous la forme du site non sécurisé, mais affichez un lien qui redirigera ensuite sur le backend (et gérera tout le token/cryptage). Lorsque vous arrivez à la version sécurisée, faites de même (ne laissez pas un paramètre "? Token = asdfjalksfjla" juste assis là dans l'URL; redirigez-le).

Ainsi, les systèmes formels basés sur des jetons ont été conçus pour résoudre ce problème, mais implémenter OAuth juste pour cela pourrait être exagéré. Passer du temps à planifier les vulnérabilités potentielles avant d'exécuter. Juste parce que ce serait vraiment difficile deviner le jeton ne signifie pas qu'il est impossible (ou il ne peut pas y avoir de collisions, etc.), alors planifiez en conséquence.

Vous pourriez également avoir besoin d'un système de gestion de session plus sophistiqué que les gestionnaires intégrés de PHP. Je ne sais pas si vous pouvez forcer PHP pour continuer une session sur plusieurs visites (les protocoles de commutation sont traités de cette façon).

1
landons

Vous pouvez gérer la session entre HTTP vers HTTPS ou HTTPS vers HTTP:

  1. Transmettre l'ID de session entre les pages à l'aide de GET

  2. ID de session POST par POST

  3. Utiliser des fichiers pour enregistrer des sessions

  4. Utiliser des cookies pour les sessions

  5. Utiliser la base de données pour enregistrer la session

L'exemple ci-dessous peut être utilisé pour transmettre en utilisant GET….

Fichier: http.php ……………

<?php

session_start();

$sessionID = session_id();

$_SESSION['demo'] = ‘Demo session between HTTP HTTPS’;

echo ‘<a href=”https://www.svnlabs.com/https.php?session=’.$sessionID.’”>Demo session from HTTP to HTTPS</a>’;

?>

Fichier: https.php ……………

<?php

$sessionID = $_GET['session'];

session_id($sessionID);

session_start();

if (!empty($_SESSION['demo'])) {
echo $_SESSION['svnlabs'];
} else {
echo ‘Demo session failed’;
}

?>

IE7: cette page contient des éléments sécurisés et non sécurisés

Vous devez utiliser un chemin relatif pour toutes les ressources statiques sur la page comme css, js, images, flash, etc. pour éviter IE message éléments sécurisés et non sécurisés…

IE Message IE Message

1
Rohan Patil

J'ai eu un problème similaire, cependant, cette solution était bonne pour moi, peut-être en aidera d'autres à l'avenir

ajoutez ceci dans votre php.ini

suhosin.session.cryptdocroot = Off

suhosin.cookie.cryptdocroot = Off

0
Willian Santana

Par défaut, je m'attendrais à ce qu'un navigateur traite les connexions à http et https comme des sessions complètement différentes. Bien que la convention soit que http: // someUrl / et https: // someUrl / pointera vers la même page, elle n'est pas garantie. Vous pouvez avoir des sites complètement différents sur le port 80 (http) et le port 443 (https).

Je ne connais pas PHP, mais en général, je ne m'attendrais pas à ce que les variables de session soient librement disponibles entre les sessions sécurisées et non sécurisées, par exemple Je ne m'attendrais pas à ce que le numéro de carte de crédit de ma dernière commande soit disponible pour toutes les pages non sécurisées suivantes que je visite.

Pardonnez la réponse sans autorité, mais je pensais que je jetterais mon 2c car il n'y a pas beaucoup de réponses.

0
codybartfast

Cela peut ne pas être possible car le cookie semble se perdre. Le navigateur que vous utilisez doit penser que c'est pour un domaine complètement différent.

Quel navigateur utilisez-vous spécifiquement?

0
Allain Lalonde

J'ai trouvé une solution par ceci .. Essayez.

$_SESSION['test'] = 'test';
session_regenerate_id(true);

header("Location: /");// the header must be sent before session close
session_write_close(); // here you could also use exit();
0
UWU_SANDUN

Avez-vous une IP dédiée? sur certains environnements partagés, le https et le http sont routés via différents serveurs, donc la commutation perd en fait l'accès aux cookies car ils se trouvent sur des domaines différents.

les solutions seraient: ip dédié

forcer https sur toutes les pages à tout moment

0
Brian Barrett