2012-04-12 14 views
41

Ho un controller che accetta i parametri del post dal modulo HTML, quindi li invierà al modello che inserirà l'array nel database Cassandra.Rimuovere tutti gli elementi dell'array tranne quello che voglio?

È SQLInjection proof, perché è NoSQL, tuttavia quello che temo è che l'utente possa semplicemente simulare i parametri di 100k post o aggiungere solo alcuni di cui non ho bisogno e che verrà inserito nel database. Come posso assicurarmi che solo i valori di cui ho bisogno rimarranno nel mio array.

Esempio:

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

Come posso essere sicuro che il mio array disinserire tutti gli elementi che non sono in buona esempio?

risposta

40

Stai cercando 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.

Naturalmente questo esempio specifico non ha molto senso perché funziona sulla matrice valori, ma c'è anche array_intersect_key che fa la stessa base di chiavi.

+0

Hmm, cosa sto facendo male in questo esempio? http://codepad.viper-7.com/mhJ0WK – sed

+1

@Qmal: '$ good' ha nomi validi come * valori *, mentre' $ post' li ha come * chiavi *. La soluzione più semplice sarebbe quella di passare in 'array_flip ($ good)' invece di '$ good' in modo che entrambi gli input abbiano i buoni nomi come chiavi. – Jon

+0

Okey, funziona ora. Grazie. – sed

1

Utilizzare l'intersezione della matrice. array intersect, ti aiuterà.

1

Questo verrà visualizzato come $ post_allowed. Quello che fa è solo consentire i valori in $ post_input che sono presenti anche in $ 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

Con whitelist le voci che si fai si aspettano.

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

In ogni caso, utilizzando Cassandra come un data-store è, naturalmente, non è una ragione per non fare la convalida sui dati che stai ricevendo.

+0

Grazie. Molto pulito e chiaro –

+0

Questa è la migliore risposta! Semplice ed esattamente ciò che è stato richiesto :) Grazie –

1

Questo è chiamato elenco bianco, il tuo esempio è fuorviante in quanto lo $_POST è un array di associazione.

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

Questa è una funzione di whitelist che ho creato per gli array associativi.

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

Nel caso in cui hai a che fare con gli array associativi e non si desidera utilizzare array_intersect_key() per qualsiasi motivo, si può anche fare un approccio più semplice di creare manualmente un nuovo array con i valori desiderati dal vecchio 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 ricordare che, mentre array_intersect e array_intersect_key sono buoni potrebbero benissimo essere eccessivo. Nella mia situazione volevo solo 1 elemento rimasto, quindi l'opzione più semplice era solo per ricostruire l'array che volevo in base alla chiave/i valori di cui avevo bisogno. Mi chiedo a che punto quindi l'array_intersect non ne valga la pena e tu stai semplicemente meglio con $new = array('whatI'=>'want');. Credo che nel PO questo valga la pena, ma in casi più piccoli potrebbe essere eccessivo.

In alternativa alla domanda iniziale, semplicemente utilizzando unset potrebbe essere stata un'opzione più economica - unset($post['one'],$post['two'],$post['three']). Ancora una volta, si riferisce al punto in cui questo diventa troppo inefficiente e le funzioni di array_intersect sono migliori.

1

Che dire dell'array multidimensionale? Sono stato ricercato per un paio d'ore per questa soluzione, da nessuna parte ho trovato una soluzione ottimale. Così, ho scritto da solo

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: ad esempio

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

      ], 
     ], 
    ]; 

chiamata: esempio

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

uscita:

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

chiavi in ​​modo da ottenere solo necessario da l'array multidimensionale. non è limitata solo per "multidimensionale", è possibile utilizzarlo passando un array come

['key1', 'loaa'] 

uscita si ottiene:

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

applausi!

Problemi correlati