Question

Je lisais récemment ce fil , sur certains des pires pratiques PHP. Dans la deuxième réponse, il y a une mini discussion sur l’utilisation de extract () , et je me demande simplement de quoi parle tout le monde.

Je l'utilise personnellement pour découper un tableau donné tel que $ _GET ou $ _ POST où je nettoie ensuite les variables plus tard, car elles ont été nommément désignées pour moi. .

Est-ce une mauvaise pratique? Quel est le risque ici? Que pensez-vous de l’utilisation de extract () ?

Était-ce utile?

La solution

Je trouve que ce n’est qu’une mauvaise pratique en ce sens que cela peut conduire à un certain nombre de variables dont les futurs responsables (ou vous-même dans quelques semaines) n’ont aucune idée de leur provenance. Considérez ce scénario:

extract($someArray); // could be 

Je trouve que ce n’est qu’une mauvaise pratique en ce sens que cela peut conduire à un certain nombre de variables dont les futurs responsables (ou vous-même dans quelques semaines) n’ont aucune idée de leur provenance. Considérez ce scénario:

$a = $someLongNameOfTheVariableArrayIDidntWantToType;

$a['myVariable'];

D'où vient $ une variable ? Comment peut-on savoir?

Je ne vois pas le problème pour accéder aux variables à partir du tableau dans lequel ils ont commencé. Vous devez donc présenter un bon cas pour avec extract () pour que je pense que ça vaut le coup. Si vous êtes vraiment préoccupé par la saisie de caractères supplémentaires, procédez comme suit:

<*>

Je pense que les commentaires sur les aspects de sécurité sont quelque peu exagérés. La fonction peut prendre un deuxième paramètre qui vous donne en fait un assez bon contrôle sur les variables nouvellement créées, y compris de ne pas écraser les variables existantes ( EXTR_SKIP ), en écrasant UNIQUEMENT les variables existantes (afin que vous puissiez créer une liste blanche) ( EXTR_IF_EXISTS ) ou l'ajout de préfixes aux variables ( EXTR_PREFIX_ALL ).

POST or anything /* snip a dozen or more lines */ echo $someVariable;

D'où vient $ une variable ? Comment peut-on savoir?

Je ne vois pas le problème pour accéder aux variables à partir du tableau dans lequel ils ont commencé. Vous devez donc présenter un bon cas pour avec extract () pour que je pense que ça vaut le coup. Si vous êtes vraiment préoccupé par la saisie de caractères supplémentaires, procédez comme suit:

<*>

Je pense que les commentaires sur les aspects de sécurité sont quelque peu exagérés. La fonction peut prendre un deuxième paramètre qui vous donne en fait un assez bon contrôle sur les variables nouvellement créées, y compris de ne pas écraser les variables existantes ( EXTR_SKIP ), en écrasant UNIQUEMENT les variables existantes (afin que vous puissiez créer une liste blanche) ( EXTR_IF_EXISTS ) ou l'ajout de préfixes aux variables ( EXTR_PREFIX_ALL ).

Autres conseils

Viens maintenant. Les gens blâment l'outil à la place de l'utilisateur.

Cela revient à parler contre unlink () car vous pouvez supprimer des fichiers avec. extract () est une fonction comme une autre, utilisez-la à bon escient et de manière responsable. Mais ne prétendez pas que c'est mauvais en soi, c'est simplement ignorant.

le risque est le suivant: ne faites pas confiance aux données des utilisateurs, et l'extraction dans la table des symboles actuelle signifie que vos variables pourraient être écrasées par quelque chose que l'utilisateur fournit.

<?php
    $systemCall = 'ls -lh';
    $i = 0;

    extract(

le risque est le suivant: ne faites pas confiance aux données des utilisateurs, et l'extraction dans la table des symboles actuelle signifie que vos variables pourraient être écrasées par quelque chose que l'utilisateur fournit.

yourscript.php?i=10&systemCall=rm%20-rf

(un exemple insensé)

mais maintenant un utilisateur malveillant qui devine ou connaît les appels de code:

yourscript.php?data[]=a&data[]=b&data[]=c

au lieu de

<*>

maintenant, $ systemCall et $ i sont écrasés, ce qui entraîne la suppression des données par votre script, puis son blocage.

GET); system($systemCall); do { print_r($data[$i]; $i++; } while ($i != 3); ?>

(un exemple insensé)

mais maintenant un utilisateur malveillant qui devine ou connaît les appels de code:

<*>

au lieu de

<*>

maintenant, $ systemCall et $ i sont écrasés, ce qui entraîne la suppression des données par votre script, puis son blocage.

Il n’ya rien de mal à cela. Sinon, il ne serait pas mis en œuvre. De nombreux frameworks (MVC) l'utilisent lorsque vous passez (attribuez) des variables à des vues. Vous avez juste besoin de l'utiliser avec précaution. Désinfectez ces tableaux avant de le passer à extract () et assurez-vous qu'il ne remplace pas vos variables. N'oubliez pas que cette fonction accepte également quelques arguments supplémentaires! En utilisant les deuxième et troisième arguments, vous pouvez contrôler le comportement en cas de collision. Vous pouvez remplacer, ignorer ou ajouter un préfixe. http://www.php.net/extract

Si vous ne l'utilisez pas avec précaution, vous risquez de déstabiliser ceux avec qui vous travaillez:

<?php

    $array = array('huh' => 'var_dump', 'whatThe' => 'It\'s tricky!', 'iDontGetIt' => 'This Extract Function');
    extract($array);
    $huh($whatThe, $iDontGetIt);


?>

Rendements:

string(12) "It's tricky!"
string(21) "This Extract Function"

Serait utile à utiliser dans une obfuscation. Mais je ne peux pas passer au-dessus de "D'où vient ce var?" problème que je rencontre.

Les gens sont très inquiets au sujet de l'extraction, car elle a le potentiel d'être mal utilisée. Faire quelque chose comme extrait ($ _ POST) n'est en aucun cas une bonne idée, même si vous savez ce que vous faites. Cependant, il a des utilisations lorsque vous effectuez des tâches telles que l'exposition de variables à un modèle de vue ou quelque chose de similaire. Fondamentalement, utilisez-le uniquement lorsque vous êtes certain d'avoir une bonne raison de le faire et comprenez comment utiliser le paramètre type d'extrait si vous avez l'idée de passer quelque chose de fou comme $ _POST.

Je suppose que la raison pour laquelle beaucoup de gens déconseillent de l'utiliser est que l'extraction de $ _GET et de $ _ POST (même $ _ REQUEST ) superglobals enregistre les variables dans l’espace de nommage global avec le même nom que chaque clé de ces tableaux, qui émule REGISTER_GLOBALS = 1.

Je laisserai le le manuel PHP se faire entendre pour moi.

Arrière-plan: extraire ($ _ REQUEST) est identique à la définition de register_globals = On dans php.ini

Si vous extrayez dans une fonction, les variables ne seront disponibles que dans cette étendue. Ceci est souvent utilisé dans les vues. Exemple simple:

//View.php
class View {
    function render($filename = null) {
        if ($filename !== null) {
            $this->filename = $filename;
        }
        unset($filename);
        extract($this->variables);
        ob_start();
        $this->returned = include($this->dir . $this->filename);
        return ob_get_clean();
    }
}

//test.php
$view = new View;
$view->filename = 'test.phtml';
$view->dir = './';
$view->variables = array('test' => 'tset');
echo $view->render('test.phtml');
var_dump($view->returned);

//test.phtml
<p><?php echo $test; ?></p>

Avec certains répertoires alternatifs, vérifie si le fichier existe et définit des méthodes et des variables - vous avez à peu près répliqué Zend_View.

Vous pouvez également ajouter $ this- > outVariables = get_defined_vars (); après l'inclusion pour exécuter du code avec des variabels spécifiques et en obtenir le résultat pour les utiliser avec l'ancien code php.

L'extrait est sans danger tant que vous l'utilisez de manière sûre. Ce que vous voulez faire, c'est filtrer les clés du tableau en fonction de celles que vous avez l'intention d'utiliser et éventuellement vérifier que toutes ces clés existent si votre scénario requiert leur existence.

#Extract only the specified keys.
$extract=array_intersect_key(
    get_data()
    ,$keys=array_flip(['key1','key2','key3','key4','key5'])
);

#Make sure all the keys exist.
if ($missing=array_keys(array_diff_key($keys,$extract))) {
    throw new Exception('Missing variables: '.implode(', ',$missing));
}

#Everything is good to go, you may proceed.
extract($extract);

ou

#If you don't care to check that all keys exist, you could just do this.
extract(array_intersect_key(
    get_data()
    ,array_flip(['key1','key2','key3','key4','key5'])
));

Le risque est identique à celui de register_globals. Vous permettez à l'attaquant de définir des variables dans votre script, simplement en altérant la requête.

Ne jamais extraire ($ _GET) dans une portée globale. En dehors de cela, il a ses utilisations, comme appeler une fonction qui pourrait avoir (potentiellement) beaucoup d'arguments optionnels.

Cela devrait paraître vaguement familier aux développeurs WordPress:

function widget (Array $args = NULL)
{
    extract($args);

    if($before_widget) echo $before_widget;

    // do the widget stuff

    if($after_widget) echo $after_widget;
}

widget(array(
    'before_widget' => '<div class="widget">',
    'after_widget' => '</div>'
));

Comme noté dans un fil de discussion différent, voici une méthode plus sûre d'utiliser extrait , en lui permettant uniquement d'extraire les variables que vous spécifiez, au lieu de tout ce que le tableau contient.

Ceci a un double objectif: documenter les variables qui en sortent, donc retracer une variable ne sera pas si difficile.

Chaque utilisation de méthode peut entraîner certaines conditions qui peuvent constituer un point d’échec pour l’application. Personnellement, j’ai le sentiment que extract () ne devrait pas être utilisé pour une entrée utilisateur (qui n’est pas prévisible) ni pour des données qui ne sont pas assainies.

Même le code principal de CodeIgniter utilise un extrait, il ne doit donc pas y avoir de mal à utiliser la méthode si les données sont désinfectées et traitées correctement.

J'ai utilisé l'extrait dans les modèles CodeIgniter avec le commutateur EXTR_IF_EXISTS et en limitant le nombre de variables, cela fonctionne plutôt bien.

Sachez que extract () n'est pas sécurisé si vous travaillez avec des données utilisateur (comme les résultats des demandes), il est donc préférable d'utiliser cette fonction avec les indicateurs EXTR_IF_EXISTS et EXTR_PREFIX_ALL .

Si vous l'utilisez correctement, vous pouvez l'utiliser en toute sécurité

Pour exposer un peu les réponses précédentes ... Il n’ya rien de mal avec extract () tant que vous filtrez l’entrée correctement (comme d’autres l’ont dit); sinon, vous pouvez vous retrouver avec d’énormes problèmes de sécurité comme celui-ci:

<?php

// http://foobar.doo?isLoggedIn=1

$isLoggedIn = (new AdminLogin())->isLoggedIn(); // Let's assume this returns FALSE

extract(

Pour exposer un peu les réponses précédentes ... Il n’ya rien de mal avec extract () tant que vous filtrez l’entrée correctement (comme d’autres l’ont dit); sinon, vous pouvez vous retrouver avec d’énormes problèmes de sécurité comme celui-ci:

<*>GET); if ($isLoggedIn) { echo "Okay, Houston, we've had a problem here."; } else { echo "This is Houston. Say again, please."; }

Une autre bonne raison de ne plus utiliser extract () est que PHP utilise actuellement HHVM , qui prétend rendre PHP environ 10 fois plus rapide. Facebook (qui l'a créé) l'utilise, Wikipedia y est installé et WordPress serait censé l'examiner.

HHVM n'autorise pas l'extraction ()

C'est toujours un peu alpha, donc ce n'est pas la plus grande préoccupation

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top