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

ale*_*exw 7 php xss json slim twig

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

我知道我可以使用PHP的本机echo json_encode(...)功能,但如果我的数据库包含HTML实体,这会产生潜在的XSS漏洞.Twig应该负责适当地逃避我的输出.

我知道这个问题,但它似乎没有提供相关的答案.我也知道json_encode过滤器,但是当我这样做时:

/api/users-json.twig

{
    "rows"  : {{rows | json_encode}}
}
Run Code Online (Sandbox Code Playgroud)

/ 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);
Run Code Online (Sandbox Code Playgroud)

响应如下:

{
    "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;}]
}
Run Code Online (Sandbox Code Playgroud)

如果没有进一步处理,这是不可解释的客户端.根据我的浏览器,内容类型被正确设置为application/json.

当然,我可以这样做: /api/users-json.twig

{
    "rows"  : {{rows | json_encode | raw}}
}
Run Code Online (Sandbox Code Playgroud)

这给了我回应:

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

但是如果我要在客户端代码中呈现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;"}]
}
Run Code Online (Sandbox Code Playgroud)

请注意,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));
Run Code Online (Sandbox Code Playgroud)

生产:

{"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;"}]}
Run Code Online (Sandbox Code Playgroud)

但我仍然不确定这是否应该用Twig做"应该".

有没有办法用Slim和Twig做到这一点?或者,我是完全错误的轨道,并且我的客户端(JS)代码是否应该在呈现之前正确地转义内容?

Rob*_*len 0

Twig 会将任何给定的变量渲染为 html 编码。但是,当您想要对结果进行 json 编码时,您需要自己迭代数据,因为 Twig 不会为您深入研究数组。