2012-04-12 11 views
41

Tengo un controlador que toma los parámetros de la publicación desde un formulario HTML, y luego los envía al modelo que insertará la matriz en la base de datos de Cassandra.Eliminar todos los elementos de la matriz, excepto lo que quiero?

Es prueba de SQLInjection, porque es NoSQL, sin embargo lo que me temo es que el usuario puede simular 100k post parámetros o simplemente agregar algunos que no necesito y se insertará en la base de datos. ¿Cómo puedo asegurarme de que solo los valores que necesito permanezcan en mi matriz?

Ejemplo:

$post = ['parent_id', 'type', 'title', 'body', 'tags']; // Good 
$post = ['parent_id', 'type', 'title', 'body', 'tags', 'one', 'two', 'three'] // Bad 

¿Cómo asegurarse de que mi matriz se desarmará todos los elementos que no están en buena ejemplo?

Respuesta

40

Usted está buscando array_intersect:

$good = ['parent_id', 'type', 'title', 'body', 'tags']; 
$post = ['parent_id', 'type', 'title', 'body', 'tags', 'one', 'two', 'three']; 

print_r(array_intersect($good, $post)); 

See it in action.

Por supuesto, este ejemplo específico no tiene mucho sentido porque funciona en los valores de matriz , pero también existe array_intersect_key que hace lo mismo en función de las claves.

+0

Hmm, ¿qué estoy haciendo mal en este ejemplo? http://codepad.viper-7.com/mhJ0WK – sed

+1

@Qmal: '$ good' tiene buenos nombres como * values ​​*, mientras que' $ post' los tiene como * keys *. La solución más simple sería pasar 'array_flip ($ good)' en lugar de '$ good' para que ambas entradas tengan los nombres correctos como claves. – Jon

+0

Okey, funciona ahora. Gracias. – sed

1

Esto dará como resultado lo mismo que $ post_allowed. Lo que hace es solo permitir los valores en $ post_input que también están presentes en $ post_allow.

$post_allowed = ['parent_id', 'type', 'title', 'body', 'tags']; 
$post_input = ['parent_id', 'type', 'title', 'body', 'tags', 'one', 'two', 'three']; 
$post = array_intersect($post_input, $post_allowed); 
66

Por lista blanca las entradas que hace esperar.

<?php 
$post = array( 
    'parent_id' => 1, 
    'type' => 'foo', 
    'title' => 'bar', 
    'body' => 'foo bar', 
    'tags' => 'foo, bar', 
    'one' => 'foo', 
    'two' => 'bar', 
    'three' => 'qux' 
); 

$whitelist = array(
    'parent_id', 
    'type', 
    'title', 
    'body', 
    'tags' 
); 

$filtered = array_intersect_key($post, array_flip($whitelist)); 

var_dump($filtered); 

De todos modos, el uso de Cassandra como un almacén de datos es, por supuesto, no es una razón para no hacer la validación de los datos que está recibiendo.

+0

Gracias. Muy limpio y claro –

+0

¡Esta es la mejor respuesta! Simple y exactamente lo que se requería :) Gracias –

1

Esto se llama lista blanca, su ejemplo es engañoso ya que $_POST es una matriz de asociación.

$post = [ 
    'parent_id' => 'val', 
    'type' => 'val', 
    'title' => 'val', 
    'body' => 'val', 
    'tags' => 'val', 
    'one' => 'val', 
    'two' => 'val', 
    'three'=>'val', 
]; 

$whitelist = ['parent_id', 'type', 'title', 'body', 'tags']; 

$sanitized_post = array_whitelist_assoc($post, $whitelist); 

Esta es una función de lista blanca que creé para las matrices asociativas.

if(!function_exists('array_whitelist_assoc')){ 

    /** 
    * Returns an associative array containing all the entries of array1 which have keys that are present in all the arguments when using their values as keys. 
    * 
    * @param array $array The array with master keys to check. 
    * @param array $array2 An array to compare keys against its values. 
    * @return array $array2,... A variable list of arrays to compare. 
    * 
    */ 

    function array_whitelist_assoc(Array $array1, Array $array2) { 

     if(func_num_args() > 2){ 
      $args = func_get_args(); 
      array_shift($args); 
      $array2 = call_user_func_array('array_merge', $args); 
     } 
     return array_intersect_key($array1, array_flip($array2)); 
    } 
} 
1

En caso de que usted está tratando con matrices asociativas y usted no desea utilizar array_intersect_key() por cualquier motivo, también se puede hacer una aproximación más simple de construir manualmente una nueva matriz con los valores que desee en el viejo uno.

$post = array(
    'parent_id' => 1, 
    'type' => "post", 
    'title' => "Post title", 
    'body' => "Post body", 
    'tags' => "Post tags", 
    'malicious' => "Robert'); DROP TABLE students;--" 
); 
$good = array(
    'parent_id' => $post['parent_id'], 
    'type' => $post['type'], 
    'title' => $post['title'], 
    'body' => $post['body'], 
    'tags' => $post['tags'] 
); 
0

Vale la pena recordar que, si bien array_intersect y array_intersect_key son buenos que bien podría ser una exageración. En mi situación, solo quería que quedara 1 elemento, por lo tanto, la opción más simple era simplemente reconstruir la matriz que quería según las claves/valores que necesitaba. Me pregunto en qué punto, por lo tanto, el array_intersect no vale la pena y simplemente está mejor con $new = array('whatI'=>'want');. Creo que en el OP vale la pena, pero en casos más pequeños podría ser excesivo.

Alternativamente en respuesta a la pregunta original, simplemente usando unset podría haber sido una opción más barata - unset($post['one'],$post['two'],$post['three']). Sin embargo, una vez más, se relaciona con el punto en el que esto se vuelve demasiado ineficiente y las funciones array_intersect son mejores.

1

¿Qué ocurre con la matriz multidimensional? Fui investigado durante un par de horas por esta solución, en ninguna parte encontré una solución óptima. Por lo tanto, he escrito por mí mismo

function allow_keys($arr, $keys) 
    { 
     $saved = []; 

     foreach ($keys as $key => $value) { 
      if (is_int($key) || is_int($value)) { 
       $keysKey = $value; 
      } else { 
       $keysKey = $key; 
      } 
      if (isset($arr[$keysKey])) { 

       $saved[$keysKey] = $arr[$keysKey]; 
       if (is_array($value)) { 

        $saved[$keysKey] = allow_keys($saved[$keysKey], $keys[$keysKey]); 
       } 
      } 
     } 
     return $saved; 
    } 

uso: ejemplo

$array = [ 
     'key1' => 'kw', 
     'loaa'=> ['looo'], 
     'k' => [ 
      'prope' => [ 
       'prop' => ['proo', 'prot', 'loolooo', 'de'], 
       'prop2' => ['hun' => 'lu'], 
      ], 
      'prop1' => [ 

      ], 
     ], 
    ]; 

de llamadas: ejemplo

allow_keys($array, ['key1', 'k' => ['prope' => ['prop' => [0, 1], 'prop2']]]) 

de salida:

Array ([key1] => kw [k] => Array ([prope] => Array ([prop] => Array ([0] => proo [1] => prot) [prop2] => Array ([hun] => lu)))) 

teclas de modo que sólo se les necesitaba de la matriz multidimensional. no se limita sólo para "multidimensional", que se puede utilizar pasando un array como

['key1', 'loaa'] 

de salida que se obtiene:

Array ([key1] => kw [loaa] => Array ([0] => looo)) 

saludos!

Cuestiones relacionadas