React是怎么防范XSS攻击的
常规的前端防范XSS攻击方式是通过对敏感字符进行转义完成的。
function escape(str) {
str = str.replace(/&/g, '&')
str = str.replace(/</g, '<')
str = str.replace(/>/g, '>')
str = str.replace(/"/g, '&quto;')
str = str.replace(/'/g, ''')
str = str.replace(/`/g, '`')
str = str.replace(/\//g, '/')
return str
}
在React内部也针对XSS攻击做了设计:
ReactDOM 负责DOM层的所有事务,在渲染所有输入内容前,就会默认进行转义。所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止 XSS(cross-site-scripting, 跨站脚本)攻击。
这样前端层的防范工作大致完成了。
那么如果使用React进行SSR,这个时候它是如何防范的呢?
先来看一下React是如何转换vDOM的:
在编写React代码时,我们通常采用JSX的方式,无需关心JSX是如何创建出vDOM对象的,以及后续是如何创建成DOM元素的(render()
)。
每个 JSX 元素只是调用 React.createElement(component, props, ...children) 的语法糖。因此,使用 JSX 可以完成的任何事情都可以通过纯 JavaScript 完成。
React.createElement
是React Core中的全局API,该方法调用方式为:
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
它实际上创建了一个这样的对象
// 注意:这是简化过的结构
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world!'
}
};
再来看完全版
上图中,我们今天的问题需要核心关注的属性是 $$typeof
, type 和 props属性我们都能够理解,$$typeof
是什么鬼?
这其实就是React为防范XSS攻击做的另外一层设计。
假设这么一个场景,服务端允许用户可以提交一个JSON格式的数据,那么看完vDOM的构建流程就会发现这个JSON数据是可以被用来构建vDOM,进而触发XSS攻击
const dangerData = {
type: stealYourPassword(), // DANGER!!
props: {
className: 'greeting',
children: 'Hello, world!'
}
};
但是 React 会使用$$typeof
来检验标记是否安全,并且使用Symbol数据类型作为value;
因为JSON中无法传递 Symbol 格式数据,而如果 dangerData
中如果没有有效的 $$typeof
value,则会被 React 判定为无效数据,直接潇洒走身甚至不留下一句废话(拒绝处理)。
React就是通过以上2种方式防范XSS攻击。 Salute~
Salute~(ps: 评论内容不少于一个汉字有些强人所难
@Zander 去年有一波bot经常来刷垃圾评论就卡了一下留言机制~