Node.js 服务器端渲染(SSR)
1.11.1 【必须】安全的Vue服务器端渲染(Vue SSR)
- 禁止直接将不受信的外部内容传入
{{{ data }}}
表达式中
- 模板内容禁止被污染
// bad: 将用户输入替换进模板
const app = new Vue({
template: appTemplate.replace("word", __USER_INPUT__),
});
renderer.renderToString(app);
- 对已渲染的HTML文本内容(renderToString后的html内容)。如需再拼不受信的外部输入,应先进行安全过滤,具体请参考1.6.3
// bad: 渲染后的html再拼接不受信的外部输入
return new Promise(((resolve) => {
renderer.renderToString(component, (err, html) => {
let htmlOutput = html;
htmlOutput += `${__USER_INPUT__}`;
resolve(htmlOutput);
});
}));
1.11.2 【必须】安全地使用EJS、LoDash、UnderScore进行服务器端渲染
- 使用render函数时,模板内容禁止被污染
lodash.Template:
// bad: 将用户输入送进模板
const compiled = _.template(`<b>${__USER_INPUT__}<%- value %></b>`);
compiled({ value: "hello" });
ejs:
// bad: 将用户输入送进模板
const ejs = require("ejs");
const people = ["geddy", "neil", "alex"];
const html = ejs.render(`<%= people.join(", "); %>${__USER_INPUT__}`, { people });
- Ejs、LoDash、UnderScore提供的HTML插值模板默认形似
<%= data %>
,尽管在默认情况下<%= data %>
存在过滤,在编写HTML插值模板时需注意:
- 用户输入流入html属性值时,必须使用双引号包裹:
<base data-id = "<%= __USER_INPUT__ %>">
- 用户输入流入
<script></script>
标签或on*的html属性中时,如<script>var id = <%= __USER_INPUT__ %></script>
,须按照1.6.3中的做法或白名单方法进行过滤,框架/组件的过滤在此处不起作用
1.11.3 【必须】在自行实现状态存储容器并将其JSON.Stringify序列化后注入到HTML时,必须进行安全过滤