3

さまざまなソースから取得したデータの一般的なサニタイザーを確立したいと考えています。サニタイズとは、(この段階で) htmlspecialchars を文字列に適用することを意味します。現在、これらのソースから取得されるデータは、オブジェクトから配列、文字列まで、すべてネストされた (そして複雑な) ものであり、形式は常に少し異なります。

そこで、配列とオブジェクトに適用され、htmlspecialchars を文字列にのみ適用する再帰的な htmlspecialchars 関数を考えましたが、オブジェクトを再帰的に処理するにはどうすればよいでしょうか?

ありがとう。

編集:私はこれについて言及すべきだったと思います-私は実際に、クライアントサーバー通信のためにJSとJSONに大きく依存するRIAを構築しています。サーバーが行う唯一のことは、データベースからデータを取得し、それを次の形式で JSON 経由でクライアントに返すことです。

{"stat":"ok","data":{...}}

前述したように、データは、文字列の形式で DB から取得されるだけでなく、XML から取得されるものでもかまいません。JSON を処理するワークフローは次のとおりです。

  1. DB/XML からデータを取得します (ソース エンコーディングは iso-8859-1)
  2. それらを「データ」配列に入れます

  3. を使用して iso-8859-1 から utf-8 に再帰的に変換します

    private function utf8_encode_deep(&$input) {
    if (is_string($input)) {
        $input = $this -> str_encode_utf8($input);
    } else if (is_array($input)) {
        foreach ($input as &$value) {
            $this -> utf8_encode_deep($value);
        }
    
        unset($value);
    } else if (is_object($input)) {
        $vars = array_keys(get_object_vars($input));
    
        foreach ($vars as $var) {
            $this -> utf8_encode_deep($input -> $var);
        }
    }
    }
    
  4. PHPjson_encodeを使用してデータを JSON に変換する

  5. クライアントにデータを送信 (エコー)

  6. JS を使用してデータをレンダリングする (例: テーブルに入れる)

その中間のどこかで、データを何らかの方法でサニタイズする必要があります (この段階では htmlspecialchars のみ)。ここでの質問は次のとおりです。どの方法を使用して、どこをサニタイズしますか?

4

4 に答える 4

1

HTMLに出力するときだけエスケープしたいでしょう。また、完全な配列またはオブジェクトを HTML に出力することはできないため、すべてをエスケープすることは無効に思えます。

JSON 出力のため、1 レベルの間接性があります。そのため、PHP でデータが使用されるコンテキストを決定することはできません。JSON は HTML ではなくプレーン テキストのままです。

したがって、JSON 内のデータを HTML 用にエスケープする必要があるかどうかを判断するには、Javascript が JSON データをどのように使用しているかを知る必要があります。

例: JSON がプレーン テキストとして表示され、 のようなものが含まれている<b>BOLD</b>場合、HTML 内で使用されたときに期待される結果は、HTML タグのように見える文字を含むが、太字のタイプセットではない、まさにこのテキストです。これは、Javascript クライアントがこのテストをプレーン テキストとして処理する場合にのみ発生します。たとえば、HTML タグをアクティブにするため、ページに配置するために使用しないinnerHTML()でください。innerText()textContent().text()

一方、JSON に にフィードされる既製の HTML が含まれていると予想される場合は、JSON にinnerHTML()入れる前にこの文字列をエスケープする必要があります。ただし、書式設定を追加したくない場合にのみ、文字列全体をエスケープする必要があります。そうしないと、定義済みの書式設定をユーザー コンテンツと混合するためにテンプレートを使用する状況になります。ユーザー コンテンツは、HTML コンテキストに入れるときにエスケープする必要がありますが、結果はエスケープしてはなりませんinnerHTML()

基本的に、Javascript によって HTML コンテキストで使用されることがすべてわかっていない限り、配列またはオブジェクト内のすべてのグローバル エスケープは間違っている可能性があります。

于 2012-10-03T17:31:30.837 に答える
1

以下を試すことができます

class MyClass {
    public $var1 = '<b>value 1</b>';
    public $var2 = '<b>value 2</b>';
    public $var3 = array('<b>value 3</b>');
}

$list = array();
$list[0]['nice'] = range("A", "C");
$list[0]['bad'] = array("<div>A</div>","<div>B</div>","<div>C</div>",new MyClass());
$list["<b>gloo</b>"] = array(new MyClass(),"<b>WOW</b>");

var_dump(__htmlspecialchars($list));

使用する機能

function __htmlspecialchars($data) {
    if (is_array($data)) {
        foreach ( $data as $key => $value ) {
            $data[htmlspecialchars($key)] = __htmlspecialchars($value);
        }
    } else if (is_object($data)) {
        $values = get_class_vars(get_class($data));
        foreach ( $values as $key => $value ) {
            $data->{htmlspecialchars($key)} = __htmlspecialchars($value);
        }
    } else {
        $data = htmlspecialchars($data);
    }
    return $data;
}

出力のようなもの

array
  0 => 
    array
      'nice' => 
        array
          0 => string 'A' (length=1)
          1 => string 'B' (length=1)
          2 => string 'C' (length=1)
      'bad' => 
        array
          0 => string '&lt;div&gt;A&lt;/div&gt;' (length=24)
          1 => string '&lt;div&gt;B&lt;/div&gt;' (length=24)
          2 => string '&lt;div&gt;C&lt;/div&gt;' (length=24)
          3 => 
            object(MyClass)[1]
              ...


    array
      0 => 
        object(MyClass)[2]
          public 'var1' => string '&lt;b&gt;value 1&lt;/b&gt;' (length=26)
          public 'var2' => string '&lt;b&gt;value 2&lt;/b&gt;' (length=26)
          public 'var3' => 
            array
              ...
于 2012-10-03T18:02:23.603 に答える
0
function htmlrecursive($data){
    if (is_array($data) && count($data) > 1){
        foreach ($data as &$d){
            $d = htmlrecursive($d);
        }
    } else if (!is_array($data)){
        return htmlspecialchars($data);
    }
    else {
         return htmlspecialchars($data[0])
    }
}

htmlrecursive($array);
于 2012-10-03T17:29:31.250 に答える
0

ArrayAccess インターフェイスを実装する必要があるオブジェクトの場合、配列ウォーク再帰を実行できます

この質問も確認してくださいPHPでarray_walk_recursiveを使用するオブジェクトを取得する

于 2012-10-03T17:32:00.570 に答える