使用 Twig 生成纯 JSON 响应是不是合适?

Posted

技术标签:

【中文标题】使用 Twig 生成纯 JSON 响应是不是合适?【英文标题】:Is it appropriate to use Twig to generate pure JSON responses?使用 Twig 生成纯 JSON 响应是否合适? 【发布时间】:2015-12-25 01:23:07 【问题描述】:

我正在尝试获取 Eloquent 查询的结果,并将其结果作为 JSON 响应输出。我的应用程序使用 Slim 和 Twig 来生成 html 响应,但是我不确定是否也应该使用 Twig 来生成 JSON。

我知道我可以使用 php 的原生 echo json_encode(...) 函数,但是如果我的数据库包含 HTML 实体,这会产生潜在的 XSS 漏洞。 Twig 应该负责适当地转义我的输出。

我知道this question,但它似乎没有提供相关答案。我也知道json_encode 过滤器,但是当我这样做时:

/api/users-json.twig


    "rows"  : rows | json_encode

/api/users 控制器:

// 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的责任!

编辑:似乎 PHP 的 filter_var_arrayjson_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) 代码是否应该负责在渲染之前正确转义内容?

【问题讨论】:

我不认为防止 XSS atracks 是 Twig 的责任。为了防止它,你必须过滤你的输入,而不是输出。 @gustavo 这不正确。当然,你应该尽可能过滤你的输入,但是转义是应该在输出中完成的。转义输入是antipattern。 呃,你是在反问吗? 如果您的系统收到一条 JSON 消息,它是通过“树枝模板”生成的,对您来说是否重要?如果完全相同,则有效的JSON 响应由“twig”和“some magic system”创建。有关系吗? 无论如何我都不会使用过滤服务器端来尝试删除 JSON 响应中的 XSS。在进行输出之前,请在 javascript 中使用正确的转义和过滤。 JSON 响应的目的是将信息从您的服务器获取到您的 Javascript。关注点分离告诉我们,您的服务器端代码不应参与 Javascript 对数据的处理。 【参考方案1】:

Twig 会将任何给定的变量呈现为 html 编码。但是,由于您想对结果进行 json 编码,因此您需要自己遍历数据,因为 Twig 不会为您深入研究数组。

【讨论】:

以上是关于使用 Twig 生成纯 JSON 响应是不是合适?的主要内容,如果未能解决你的问题,请参考以下文章

Google Chrome 将 json AJAX 响应显示为树而不是纯文本,新版本

yii2 使用twig 模板引擎

Axios.get 返回纯 html 而不是 JSON 返回数据

如何在 Twig 中提取从 HTML 解析的纯文本?

Swagger 吐出 xml 响应而不是 json

尝试使用 json 数据而不是纯文本或 x-www-form-urlencoded 进行 JQuery 发布时出现 CORS 问题