Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Problème Ajax de session et headers en php.

7 réponses
Avatar
Jean Francois Ortolo
Bonjour

Deux questions :

1) Pour les appels Ajax à des scripts externes, j'ai vu sur le PHP
Manual ( commentaires ), que tout appel à session_start(), bloquait le
fichier de session.

En conséquence, il faudrait théoriquement appeler
'session_write_close()' avant chaque appel Ajax, puis 'session_start()'
après chaque appel Ajax, dans le script appelant ?


2) Dans ces scripts appelés par Ajax, pour éviter le cache, je met
des headers type "Expires", "If-Modified", etc... mais avant avoir lancé
le session_start().

Est-il vrai, que session_start() change les headers déjà lancés,
ceci même si ( c'est mon cas ), je fais un ob_start() au début du
script, et un ob_end_flush() à la fin ?

En d'autres termes, dois-je placer les headers après le
session_start(), et pas avant, pour que ces headers soient pris en compte ?

Merci beaucoup de vos réponses.

Respectueusement.

Jean François Ortolo

7 réponses

Avatar
Fred
On 20/02/2015 11:16, Jean Francois Ortolo wrote:

Bonjour



Bonjour


Deux questions :

1) Pour les appels Ajax à des scripts externes, j'ai vu sur le PHP
Manual ( commentaires ), que tout appel à session_start(), bloquait
le fichier de session.



Oui, par defaut, le fichier de session reste ouvert jusqu'à la fin du
script.



En conséquence, il faudrait théoriquement appeler
'session_write_close()' avant chaque appel Ajax, puis
'session_start()' après chaque appel Ajax, dans le script appelant ?




Oui, si le script effectue un gros traitement. Il vaut mieux
enregistrer la session avant quitte à la réouvrir en fin de script
pour mettre à jour les données. C'est inutile la plupart du temps
ou peut-être sur un mutualisé bien chargé.

Il faut aussi voir le contexte, si l'utilisateur peut faire plusieurs
appels ajax en même temps, c'est un point à prendre en compte.



2) Dans ces scripts appelés par Ajax, pour éviter le cache, je met
des headers type "Expires", "If-Modified", etc... mais avant avoir
lancé le session_start().

Est-il vrai, que session_start() change les headers déjà lancés, ceci
même si ( c'est mon cas ), je fais un ob_start() au début du script,
et un ob_end_flush() à la fin ?

En d'autres termes, dois-je placer les headers après le
session_start(), et pas avant, pour que ces headers soient pris en
compte ?





D'aprés la doc de session_cache_limiter() :

Le fait de définir le limiteur de cache à la valeur '' désactivera
automatiquement et totalement l'envoi des en-têtes de cache.

Le limiteur de cache est remis à la valeur par défaut de
session.cache_limiter à chaque démarrage de script PHP. Donc, vous
devrez appeler session_cache_limiter() à chaque page, et avant
session_start().



donc, session_start() envoie (ou écrase) les headers sauf si
session.cache_limiter est vide.

Pour voir en détail ce qui se passe (si session_start écrase les
entêtes deja créés), il y a headers_list() et headers_sent().

On peut aussi configurer le cache dans .htaccess.


Fred
Avatar
Jean Francois Ortolo
Rebonjour

J'aurais du me souvenir des conseils de Monsieur John Gallet.

En fait, le problème ne venait pas du cache.

Les identificateurs de session ( gérés par php ), semblent avoir eu
des doublons.

En d'autres termes : Au moment où j'étais sur mon site, quelqu'un
d'autre ( adresse ip différente probablement faut pas pousser ), était
connecté à la même page que moi, avec le même id de session.

Depuis ce matin, les id de session ( inscrits dans les tables MySQL
avec les enregs des données ), sont créés par une fonction
tmp_random($nbre) ( que je donnerai volontiers ), qui génère une chaîne
aléatoire ( et imprévisible ), de $nbre caractères.

Je n'ai pas besoin que cet id soit conservé entre chaque chargement
de page, il est généré en amont une fois par chargement de page.

Je tiens le code de cette fonction à votre disposition.

L'id en question est fixé à une longueur de 50 caractères.

Respectueusement.

Jean François Ortolo
Avatar
Fred
On 02/03/2015 17:10, Jean Francois Ortolo wrote:

Rebonjour



Bonjour


J'aurais du me souvenir des conseils de Monsieur John Gallet.

En fait, le problème ne venait pas du cache.

Les identificateurs de session ( gérés par php ), semblent avoir eu des
doublons.



C'est un peu gros. On a plus de chance de gagner 2 fois au loto que
d'avoir le même PHPSESSID. Quand bien même, je suppose que php vérifie
qu'il n'y a pas déjà une session active avec le même ID.



En d'autres termes : Au moment où j'étais sur mon site, quelqu'un
d'autre ( adresse ip différente probablement faut pas pousser ), était
connecté à la même page que moi, avec le même id de session.



C'est une supposition ou tu l'as vérifié sur des logs?
Ca peut aussi être un vol de session.


Depuis ce matin, les id de session ( inscrits dans les tables MySQL avec
les enregs des données ), sont créés par une fonction tmp_random($nbre)
( que je donnerai volontiers ), qui génère une chaîne aléatoire ( et
imprévisible ), de $nbre caractères.



OK. Par contre, tes ID sont conservés juste pour avoir une liste des ID
déja créés et éviter les doublons, ou pour autre chose?



Je n'ai pas besoin que cet id soit conservé entre chaque chargement de
page, il est généré en amont une fois par chargement de page.



La, par contre, ce n'est pas clair du tout, voir même inquiètant.
Je comprend que tu génère un ID différent pour chaque page et c'est
peut-être la cause du problème.

Un ID est créé pour chaque nouveau visiteur, c'est a dire si il
n'a pas de cookie PHPSESSID ou si il est expiré.
L'ID est conservé pendant toute la visite. En fait, on oublie l'ID.
et on laisse session_start() se débrouiller.

L'ID peut être changé dans certains cas par sécurité comme par exemple
quand un visiteur anonyme s'identifie sur le site.



Je tiens le code de cette fonction à votre disposition.

L'id en question est fixé à une longueur de 50 caractères.

Respectueusement.

Jean François Ortolo




Avatar
Jean Francois Ortolo
Bonjour Monsieur



Le 03/03/2015 13:40, Fred a écrit :
On 02/03/2015 17:10, Jean Francois Ortolo wrote:

Rebonjour



Bonjour


J'aurais du me souvenir des conseils de Monsieur John Gallet.

En fait, le problème ne venait pas du cache.

Les identificateurs de session ( gérés par php ), semblent avoir eu des
doublons.



C'est un peu gros. On a plus de chance de gagner 2 fois au loto que
d'avoir le même PHPSESSID. Quand bien même, je suppose que php vérifie
qu'il n'y a pas déjà une session active avec le même ID.





Il m semble avoir vu sur les commentaires de PHP Manual, que le mode
de génération des ids de session, n'était pas strictement fiable, et
pouvait donner lieu à des doublons.


En d'autres termes : Au moment où j'étais sur mon site, quelqu'un
d'autre ( adresse ip différente probablement faut pas pousser ), était
connecté à la même page que moi, avec le même id de session.



C'est une supposition ou tu l'as vérifié sur des logs?
Ca peut aussi être un vol de session.




Les ids de session ne sont pas dans les logs Apache.

Les identificateurs en question, me permettent d'identifier les
enregistrements des données à afficher dans deux tables MySQL,
lesquelles données ne servent qu'une seule fois, et sont effacées de
toute manière après 60 secondes, et aussi les données de l'id en cours
sont effacées avant insertion ( avec cet id ) des données.

Les données ne sont donc pas conservées,et il n'y a pas du tout
besoin que les ids soient identiques au cours d'une visite.

Le seul et unique critère de fiabilité, est qu'il n'y ait pas le même
id en même temps par deux visiteurs différents, au cours du chargement
d'un même *type* de page. ( Même avec des courses différentes. )

C'est le principe d'unicité et de non prévisibilité défendu par
Monsieur John Gallet sur son site : www.saphirtech.com , dont j'ai
encore un document Acrobat Reader sur la sécurité en environnement PHP.


Depuis ce matin, les id de session ( inscrits dans les tables MySQL avec
les enregs des données ), sont créés par une fonction tmp_random($nbre)
( que je donnerai volontiers ), qui génère une chaîne aléatoire ( et
imprévisible ), de $nbre caractères.



OK. Par contre, tes ID sont conservés juste pour avoir une liste des ID
déja créés et éviter les doublons, ou pour autre chose?




Pour disposer d'identifiants uniques et non prévisibles, qui ne
serviront qu'une fois.

Il sont changés à chaque chargement de page de stats d'un visiteur de
mon site.




Je n'ai pas besoin que cet id soit conservé entre chaque chargement de
page, il est généré en amont une fois par chargement de page.



La, par contre, ce n'est pas clair du tout, voir même inquiètant.
Je comprend que tu génère un ID différent pour chaque page et c'est
peut-être la cause du problème.

Un ID est créé pour chaque nouveau visiteur, c'est a dire si il
n'a pas de cookie PHPSESSID ou si il est expiré.
L'ID est conservé pendant toute la visite. En fait, on oublie l'ID.
et on laisse session_start() se débrouiller.




Celà ne m'empêche pas d'avoir des session, et un id de session ( que
j'appelle : $tmp_id_session ) global, et qui reste constant toute une
visite d'un visiteur.

L'identificateur unique et ponctuel, quant à lui, s'appelle
$tmp_tmp_id_session, est global aussi, et est créé dans mon script des
fonctions, par cette fonction : "tmp_random($nbre)".

Je peux en fournir le code si besoin, il est quand même plutôt court.

J'appelle cette fonction avec comme argument le nombre 50 ( l'id fait
50 caractères ).

L'ID peut être changé dans certains cas par sécurité comme par exemple
quand un visiteur anonyme s'identifie sur le site.




Dans ce cas, j'utiliserais des variables de session, ou bien mieux:
Un procédé aussi avec une table MySQL ( AUTHENTIFICATION ), car toutes
mes tables MySQL sont en majuscules.

J'ai une fonction make_authen(i$password), et une fonction
verif_authen() ( sans paramètre ).

Le password crypté est censé être enregistré comme variable de
session, et l'ensemble pseudo, password crypté et timestamp, dans la table.

Si du moins si j'utilisais ces fonctions, je ne les utilise pas.

Ces fonctions contenant le code d'authentification sont déjà faites,
mais je m'en sers pas, car je n'ai pas d'abonné, mon site est gratuit.

Pendant que j'y suis, je donne le code de la fonction tmp_random($nbre) :


[code]

function tmp_random($universal_key)
{
$string = "";

$user_ramdom_key =
"(aLABbCcEd1[eDf2FghR3ij4kYXQl5UmOPn6pVq7rJs8tuW9IvGwxHTy)K]Z§M_S";

srand((double)microtime(true) * time());

for($i=0; $i<$universal_key; $i++)
{
$string .=
$user_ramdom_key[rand()%strlen($user_ramdom_key)];
}

return $string;
}

[/code]


Merci de me donner vos critiques pour des améliorations à ce code.

Respectueusement.

Jean François Ortolo
Avatar
Jean Francois Ortolo
Rebonjour

J'ai corrigé la fonction tmp_random($nbre).

Maintenant, l'argument de mt_srand() change à chaque fois ( de
manière plus ou moins aléatoire dépendant du temps en microsecondes ).

Voici le code :

[code]

function tmp_random($universal_key)
{
$string = "";

$user_ramdom_key =
"(aLABbCcEd1[eDf2FghR3ij4kYXQl5UmOPn6pVq7rJs8tuW9IvGwxHTy)K]ZM_S";

unset($t);
$t =floor(0.5 + (double)(microtime() * time()));

mt_srand($t);

for($i=0; $i<$universal_key; $i++)
{
$string .=
$user_ramdom_key[mt_rand()%strlen($user_ramdom_key)];
}

return $string;
}

[/code]


Cette fonction est censé rendre un identificateur/chaîne de
caractères, non prévisible de quelque manière que ce soit, et très très
aléatoire.

En espérant que l'id soit unique, ce qui est censé dépendre surtout
du nombre de caractères ( dans mon cas j'en met 50 ).

A priori, les chaînes de caractères sont absolument aléatoires, bien
que leur génération se fasse sur le mode déterministe.

A 63 caractères différents et 50 caractères, et en supposant qu'il
n'y a pas de doublons du tout ( très peu probable et peu crédible ),
celà nous donnerait : 1 / ( 63 ** (50 - 1)) chaînes différentes possible
environ.

De toute manière, mon critère de fiabilité, est que le même id ne se
produise pas en même temps sur deux visiteurs différents.

Je pense que l'on peut dire su mon id est plus secure que les ids de
session ?

Et puis, mon id n'est pas copiable matériellement.

Pour l'instant je ne détecte plus de problème ( même avant plutôt
rare ) que j'avais attribué au cache, de non concordance entre les stats
et des pronos, et de changement de ces données après rechargement de page.

Merci de me donner vos avis et suggestions.

Respectueusement.

Jean François Ortolo
Avatar
Jean Francois Ortolo
J'ajoute...

Que j'ai configuré mon serveur VPS, pour "blinder" mes sessions :

session.entropy_file = /dev/urandom
session.entropy_length = 512

session.hash_bits_per_character = 5 ; ( [0-9a-f] )
session.hash_function = sha512 ; ( sans quotes ni double quotes )

session_use_only_cookies = 1

Le changement de fonction de hash à sha512 ( ou whirlpool ), est
possible depuis PHP >= 5.4.0.

Je n'ai pas constaté de changement de nombres de caractères de mon id
de session avec l'algorithme whirlpool, donc je le met à sha512, qui
appartient à la famille SHA. j'aurais préféré un algorithme type DES
comme whirlpool, mais à l'impossible nul n'est tenu.

Je met à 5 seulement le "session.bits_per_character", pour ne pas
avoir de virgules éventuellement dans l'id de session.

Par ailleurs mon implémentation de l'autre identificateur ( valable
une fois/chargement de page ), est fondé sur la fonction tmp_random($nbre).

Je n'ai pas besoin de blinder mon site quant à des logins d'abonnés,
mis dans le futur avoir une bonne sécurité passe par la prévention.

Bien amicalement.

Jean François Ortolo
Avatar
mrr
On 03/04/2015 09:46 PM, Jean Francois Ortolo wrote:
Cette fonction est censé rendre un identificateur/chaîne de caractères,
non prévisible de quelque manière que ce soit, et très très aléatoire.

En espérant que l'id soit unique, ce qui est censé dépendre surtout
du nombre de caractères ( dans mon cas j'en met 50 ).

A priori, les chaînes de caractères sont absolument aléatoires, bien
que leur génération se fasse sur le mode déterministe.

A 63 caractères différents et 50 caractères, et en supposant qu'il
n'y a pas de doublons du tout ( très peu probable et peu crédible ),
celà nous donnerait : 1 / ( 63 ** (50 - 1)) chaînes différentes possible
environ.

De toute manière, mon critère de fiabilité, est que le même id ne se
produise pas en même temps sur deux visiteurs différents.



Bonjour,

La probabilité d'une "collision" est en effet extrêmement faible mais
cela m'amène à me poser une question.
Si on peut se permettre de prendre ce petit risque pour un site web, le
fait-on pour une histoire de transfert d'argent ou de pilotage d'une
centrale nucléaire (exemple classique, je sais, mais au moins c'est
parlant :) )?

--
mrr