2015-09-27 2 views
6

Я пытаюсь взять результат запроса «Яркий» и вывести его результаты как ответ JSON. Мое приложение использует Slim и Twig для генерации HTML-ответов, однако я не уверен, что я должен использовать Twig для генерации JSON.Уместно ли использовать Twig для генерации чистых ответов JSON?

Я знаю, что могу использовать встроенную функцию PHP echo json_encode(...), но это создает потенциальную уязвимость XSS, если моя база данных содержит объекты HTML. Предполагается, что Twig будет отвечать за то, чтобы избежать выхода на выходе.

Я знаю this question, однако, похоже, он не дает соответствующего ответа. Я также знаю о json_encode фильтра, но когда я делаю это:

/api/users-json.twig

{ 
    "rows" : {{rows | json_encode}} 
} 

/API/пользователей контроллер:

// Simulate database query results 
$result = [ 
    "rows" => [ 
     [ 
      "user_name" => "alex", 
      "message" => "grawr!"  
     ], 
     [ 
      "user_name" => "h4xx0r", 
      "message" => "<script>alert('hello, I can execute JS on your website!');</script>"  
     ]     
    ] 
]; 

$app->response->headers->set('Content-Type', 'application/json; charset=utf-8'); 
$app->render("api/users-json.twig", $result); 

Ответ выглядит так:

{ 
    "rows" : [{&quot;user_name&quot;:&quot;alex&quot;,&quot;message&quot;:&quot;grawr!&quot;},{&quot;user_name&quot;:&quot;h4xx0r&quot;,&quot;message&quot;:&quot;&lt;script&gt;alert(&#039;hello, I can execute JS on your website!&#039;);&lt;\/script&gt;&quot;}] 
} 

Это не интерпретируемая клиентская сторона без дальнейшей обработки. Согласно моему браузеру, тип контента правильно установлен на application/json.

Я могу, конечно, сделать: /api/users-json.twig

{ 
    "rows" : {{rows | json_encode | raw}} 
} 

Который дает мне ответ:

{ 
    "rows" : [{"user_name":"alex","message":"grawr!"},{"user_name":"h4xx0r","message":"<script>alert('hello, I can execute JS on your website!');<\/script>"}] 
} 

Но если бы я, чтобы сделать h4xx0r-х сообщение в клиентском коде, я открыт для атаки XSS.

Вывод, который я считаю, было бы «правильным» будет:

{ 
    "rows" : [{"user_name":"alex","message":"grawr!"},{"user_name":"h4xx0r","message":"&lt;script&gt;alert(&#039;hello, I can execute JS on your website!&#039;);&lt;\/script&gt;"}] 
} 

Обратите внимание, что «сообщение» h4xx0r в настоящее время спасся, но структура ответа в целом сохраняется действительным JSON.

Я мог бы, конечно, прокрутить каждую строку и вручную htmlspecialchars каждое значение, а затем либо echo json_encode, либо передать его в Twig. Но похоже, что это должно быть ответственностью Twig!

Edit: Казалось бы, что РНР filter_var_array, в сочетании с json_encode, является разумной альтернативой использованию Twig:

$app->response->headers->set('Content-Type', 'application/json; charset=utf-8'); 
echo json_encode(filter_var_array($result, FILTER_SANITIZE_SPECIAL_CHARS)); 

Производит:

{"rows":[{"user_name":"alex","message":"grawr!"},{"user_name":"h4xx0r","message":"&#60;script&#62;alert(&#39;hello, I can execute JS on your website!&#39;);&#60;\/script&#62;"}]} 

Но я до сих пор не уверен, если это то, что «должно» сделать с помощью Twig.

Есть ли способ сделать это с помощью Slim и Twig? Или я полностью ошибаюсь в треке, и должен ли мой клиентский код (JS) правильно избегать содержимого перед рендерингом?

+0

Я не думаю, что предотвращение XSS atracks - ответственность Twig. Чтобы предотвратить это, вы должны фильтровать свой вход, а не вывод. –

+0

@gustavo Неправильное использование. Конечно, вы всегда должны ** фильтровать ** свой вход, когда это возможно, но ** ускорение ** - это то, что должно быть сделано на выходе. Исходный вход - это [antipattern] (http://security.stackexchange.com/a/42521/74909). – alexw

+0

Ух, ты спрашиваешь риторически? – alexw

ответ

0

Twig отобразит любую заданную переменную в виде html-кода. Тем не менее, поскольку вы хотите, чтобы json закодировал результат, вам нужно выполнить итерацию данных самостоятельно, поскольку Twig не вникает в массив для вас.