2012-04-12 15 views
41

Ich habe Controller, die Post-Parameter aus HTML-Formular nimmt, wird es dann an das Modell senden, die das Array in Cassandra-Datenbank einfügen wird.Entfernen Sie alle Array-Elemente außer was ich will?

Es ist SQLInjection Proof, weil es NoSQL ist, aber was ich fürchte ist, dass Benutzer nur 100k Post-Parameter simulieren oder nur einige, die ich brauche nicht hinzufügen und es wird in die Datenbank eingefügt werden. Wie kann ich sicherstellen, dass nur die Werte, die ich brauche, in meinem Array bleiben?

Beispiel:

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

Wie kann ich sicherstellen, dass meine Array alle Elemente unset werden, die nicht in gut Beispiel sind?

Antwort

40

Sie suchen 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.

Natürlich ist dieses spezifische Beispiel nicht viel Sinn machen, weil es Werte auf Array arbeitet, aber es gibt auch array_intersect_key, die gleich auf Schlüssel basiert tut.

+0

Hmm, was mache ich falsch in diesem Beispiel? http://codepad.viper-7.com/mhJ0WK – sed

+1

@Qmal: '$ gut' hat gute Namen als * Werte *, während '$ post' sie als * keys * hat. Die einfachste Lösung wäre, 'array_flip ($ good)' anstelle von '$ good' zu übergeben, so dass beide Eingaben die guten Namen als Schlüssel haben. – Jon

+0

Okey, funktioniert jetzt. Vielen Dank. – sed

1

Dies wird dasselbe ausgeben wie $ post_allowed. Es erlaubt nur die Werte in $ post_input, die auch in $ post_allow vorhanden sind.

$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

Durch die Einträge Whitelisting Sie tun erwarten.

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

Wie auch immer, mit Cassandra als Datenspeicher ist natürlich kein Grund, nicht die Validierung auf den Daten zu tun, die Sie erhalten.

+0

Vielen Dank. Sehr sauber und klar. –

+0

Dies ist die beste Antwort! Einfach und genau was erforderlich war :) Danke –

1

Dies wird als White Listing bezeichnet, Ihr Beispiel ist irreführend, da das $_POST ein Assoziationsarray ist.

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

Dies ist eine Whitelisting Funktion I für assoziative Arrays erstellt.

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

Falls Sie sich den Umgang mit assoziativen Arrays und Sie wollen nicht array_intersect_key() aus irgendeinem Grund verwenden, können Sie auch einen einfacheren Ansatz tun manuell ein neues Array bauen die Werte mit Ihnen aus dem alten wollen ein.

$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

Sein daran erinnert, dass während array_intersect und array_intersect_key gut sind, könnten sie auch zu viel des Guten. In meiner Situation wollte ich nur 1 Element übrig haben, daher war die einfachste Option nur das Array neu zu erstellen, das ich basierend auf den Schlüsseln/Werten, die ich brauchte, erstellen wollte. Ich frage mich, an welchem ​​Punkt die array_intersect's nicht wert sind und Sie sind einfach besser dran mit $new = array('whatI'=>'want');. Ich glaube an das OP, das ist es wert, aber in kleineren Fällen könnte es Overkill sein.

Alternativ als Antwort auf die ursprüngliche Frage könnte einfach unset eine billigere Option gewesen sein - unset($post['one'],$post['two'],$post['three']). Dies bezieht sich jedoch wiederum auf den Punkt, an dem dies zu ineffizient wird und die array_intersect-Funktionen besser sind.

1

Was ist mit multidimensionalen Array? Ich habe für diese Lösung einige Stunden recherchiert, nirgendwo eine optimale Lösung gefunden. so, ich schrieb es selbst

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; 
    } 

Verwendung: Beispiel

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

      ], 
     ], 
    ]; 

Aufruf: Beispiel

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

Ausgang:

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

so erhalten Sie nur benötigten Schlüssel aus das multidimensionale Array. es ist nicht nur für "multidimensional" beschränkt, können Sie es, indem ein Array wie

['key1', 'loaa'] 

Ausgabe, die Sie bekommen können:

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

Prost!