Pregunta

Hace poco estuve leyendo este hilo , en algunos de las peores prácticas de PHP. En la segunda respuesta, hay una mini discusión sobre el uso de extract () , y me pregunto de qué se trata todo.

Personalmente lo uso para cortar una matriz dada, como $ _GET o $ _POST , donde luego desinfecta las variables más tarde, ya que se han nombrado convenientemente para mí .

¿Es esta una mala práctica? ¿Cuál es el riesgo aquí? ¿Qué piensa sobre el uso de extract () ?

¿Fue útil?

Solución

Me parece que es una mala práctica, ya que puede conducir a una serie de variables que los futuros mantenedores (o usted mismo en unas pocas semanas) no tienen idea de dónde vienen. Considere este escenario:

extract($someArray); // could be 

Me parece que es una mala práctica, ya que puede conducir a una serie de variables que los futuros mantenedores (o usted mismo en unas pocas semanas) no tienen idea de dónde vienen. Considere este escenario:

$a = $someLongNameOfTheVariableArrayIDidntWantToType;

$a['myVariable'];

¿De dónde vino $ someVariable ? ¿Cómo puede alguien saberlo?

No veo el problema al acceder a las variables desde la matriz en la que comenzaron, por lo que realmente necesitaría presentar un buen caso para usando extract () para que yo piense que vale la pena. Si realmente le preocupa escribir algunos caracteres adicionales, simplemente haga esto:

<*>

Creo que los comentarios aquí sobre los aspectos de seguridad son demasiado exagerados. La función puede tomar un segundo parámetro que realmente le da un control bastante bueno sobre las variables recién creadas, incluyendo no sobrescribir ninguna variable existente ( EXTR_SKIP ), SOLO sobrescribir variables existentes (para que pueda crear una lista blanca) ( EXTR_IF_EXISTS ), o agregando prefijos a las variables ( EXTR_PREFIX_ALL ).

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

¿De dónde vino $ someVariable ? ¿Cómo puede alguien saberlo?

No veo el problema al acceder a las variables desde la matriz en la que comenzaron, por lo que realmente necesitaría presentar un buen caso para usando extract () para que yo piense que vale la pena. Si realmente le preocupa escribir algunos caracteres adicionales, simplemente haga esto:

<*>

Creo que los comentarios aquí sobre los aspectos de seguridad son demasiado exagerados. La función puede tomar un segundo parámetro que realmente le da un control bastante bueno sobre las variables recién creadas, incluyendo no sobrescribir ninguna variable existente ( EXTR_SKIP ), SOLO sobrescribir variables existentes (para que pueda crear una lista blanca) ( EXTR_IF_EXISTS ), o agregando prefijos a las variables ( EXTR_PREFIX_ALL ).

Otros consejos

Vamos ahora. Las personas culpan a la herramienta en lugar del usuario.

Eso es como hablar en contra de unlink () porque puedes eliminar archivos con él. extract () es una función como cualquier otra, úsala sabia y responsablemente. Pero no afirmes que es malo per se, eso es simplemente ignorante.

el riesgo es: no confíe en los datos de los usuarios, y extraer en la tabla de símbolos actual significa que sus variables podrían sobrescribirse por algo que el usuario proporcione.

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

    extract(

el riesgo es: no confíe en los datos de los usuarios, y extraer en la tabla de símbolos actual significa que sus variables podrían sobrescribirse por algo que el usuario proporcione.

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

(un ejemplo sin sentido)

pero ahora un usuario malintencionado que adivina o conoce las llamadas de código:

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

en lugar de

<*>

ahora, $ systemCall y $ i se sobrescriben, lo que hace que su script elimine sus datos primero y luego se cuelgue.

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

(un ejemplo sin sentido)

pero ahora un usuario malintencionado que adivina o conoce las llamadas de código:

<*>

en lugar de

<*>

ahora, $ systemCall y $ i se sobrescriben, lo que hace que su script elimine sus datos primero y luego se cuelgue.

No tiene nada de malo. De lo contrario, no se implementaría. Muchos marcos (MVC) lo usan cuando pasa (asigna) variables a Vistas. Solo necesita usarlo con cuidado. Desinfecte esas matrices antes de pasarlas a extract () y asegúrese de que no anule sus variables. ¡No olvide que esta función también acepta algunos argumentos más! Usando los argumentos segundo y tercero puede controlar el comportamiento si se produce una colisión. Puede anular, omitir o agregar prefijo. http://www.php.net/extract

Si no se usa con cuidado, puede confundir a los demás con los que trabaja, considere:

<?php

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


?>

Rendimientos:

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

Sería útil usarlo en una ofuscación. Pero no puedo superar el "¿De dónde vino esa var?" problema con el que me encuentro.

Las personas se entusiasman con el extracto porque tiene el potencial de ser mal utilizado. Hacer algo como extracto ($ _ POST) no es una buena idea en ningún caso, incluso si sabe lo que está haciendo. Sin embargo, tiene sus usos cuando está haciendo cosas como exponer variables a una plantilla de vista o algo similar. Básicamente, solo úselo cuando esté muy seguro de que tiene una buena razón para hacerlo, y comprenda cómo usar el parámetro de tipo de extracto si tiene la idea de pasarle algo loco como $ _POST.

Supongo que la razón por la que mucha gente no recomienda usarlo es que extrae $ _GET y $ _POST (incluso $ _REQUEST ) superglobals registra variables en el espacio de nombres global con el mismo nombre que cada clave dentro de esas matrices, que básicamente emula REGISTER_GLOBALS = 1.

Dejaré que el manual PHP hable por yo

Antecedentes: extract ($ _ REQUEST) es lo mismo que configurar register_globals = On en php.ini

Si extrae en una función, las variables solo estarán disponibles en ese ámbito. Esto se usa a menudo en las vistas. Ejemplo 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>

Con algunos directorios alternativos, verifica si el archivo existe y las variables y métodos definidos: prácticamente ha replicado Zend_View.

También puede agregar $ this- > outVariables = get_defined_vars (); después de la inclusión para ejecutar código con variables específicas y obtener el resultado de estos para usar con el código php anterior.

El extracto es seguro siempre que lo use de manera segura. Lo que desea hacer es filtrar las claves de la matriz solo a las que desea utilizar y tal vez verificar que todas esas claves existen si su escenario requiere su existencia.

#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);

o

#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'])
));

El riesgo es el mismo que con register_globals. Habilita al atacante para establecer variables en su script, simplemente manipulando la solicitud.

Nunca extraiga ($ _ GET) en un ámbito global. Aparte de eso, tiene sus usos, como llamar a una función que podría (potencialmente) tener muchos argumentos opcionales.

Esto debería parecer vagamente familiar para los desarrolladores de 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>'
));

Como alguien señaló en un hilo diferente, aquí es una forma más segura usar extracto , permitiéndole solo extraer las variables que especifique, en lugar de todo lo que contiene la matriz.

Esto tiene un doble propósito de documentar qué variables salen de él, por lo que rastrear una variable no será tan difícil.

El uso de cada método puede conducir a algunas condiciones en las que puede ser un punto de falla para la aplicación. Personalmente, creo que extract () no debe usarse para la entrada del usuario (que no es predecible) y para los datos que no están desinfectados.

Incluso el código central de CodeIgniter usa extracto, por lo que no debe haber ningún daño al usar el método si los datos se desinfectan y se manejan bien.

He usado extracto en modelos CodeIgniter con el interruptor EXTR_IF_EXISTS y limitando el número de variables, funciona bastante bien.

Tenga en cuenta que extract () no es seguro si está trabajando con datos de usuario (como resultados de solicitudes), por lo que es mejor usar esta función con las banderas EXTR_IF_EXISTS y EXTR_PREFIX_ALL .

Si lo usa bien, es seguro usarlo

Para exponer un poco sobre las respuestas anteriores ... No hay nada de malo en extract () siempre que filtre la entrada correctamente (como han dicho otros); de lo contrario, puede terminar con grandes problemas de seguridad como este:

<?php

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

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

extract(

Para exponer un poco sobre las respuestas anteriores ... No hay nada de malo en extract () siempre que filtre la entrada correctamente (como han dicho otros); de lo contrario, puede terminar con grandes problemas de seguridad como este:

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

Una buena razón adicional para dejar de usar extract () es que hay un impulso en PHP para usar HHVM que afirma hacer que PHP sea aproximadamente 10 veces más rápido. Facebook (quién lo hizo) lo está usando, Wikipedia está en él y se rumorea que WordPress lo está mirando.

HHVM no permite el extracto ()

Todavía es una especie de alfa, por lo que no es la mayor preocupación

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top