Airbnb的克隆,房屋描述的安全HTML

136 阅读4分钟

这篇文章是一个新系列的一部分,我们用Next.js建立一个克隆的Airbnb。请看第一篇文章

我们的表格很好,但我们有一个问题:房子的描述。

它是以HTML形式处理描述的。

除非我们的房主的目标受众是懂得HTML的人,否则这不会做得很好。

我们需要一个更方便用户的编辑器。

第二件事,甚至更重要的是,我们仍然没有在单页视图中,在pages/houses/[id].js 文件中。

我把这项任务推迟到现在,因为我想给你们看一些东西。

如果我们把房子的描述加到pages/houses/[id].js

...
<p>{props.house.title}</p>
<div>{props.house.description}</div>
...

我们会发现一个糟糕的惊喜。

HTML是完全可见的,而不是被解释的!就像在上面的编辑器中一样。

原因是JSX默认会对所有内容进行转义,这对于防止XSS来说是很好的,但在这种情况下却不是很好。

我们必须做的是,我们必须使用dangerouslySetInnerHTML:

pages/houses/[id].js

<div
  dangerouslySetInnerHTML={{
    __html: props.house.description
  }}></div>

来使描述被解释为HTML。

但是,如果我们不对描述进行任何过滤,房子的主人也可以在描述中写入JavaScript,比如说。

<script>alert('test')</script>

而这将在房屋页面上对浏览房屋的人运行。

这是一个XSS漏洞

让我们先做第一步--我们添加一个编辑器。

添加佩尔编辑器

我选择的编辑器是Pell

它很容易使用,而且体积小。

github.com/bpetetot/re…,也有一个React包装器可用

使用npm安装它。

npm install react-pell

然后进入components/HouseForm.js ,导入它。

import Editor from 'react-pell'

现在把

<p>
  <label>House description</label>
  <textarea
    required
    onChange={event => setDescription(event.target.value)}
    value={description}></textarea>
</p>

改成这样。

<div>
  <Editor
    onChange={html => setDescription(html)}
    defaultContent={description}
    actions={['bold', 'underline', 'italic']}
  />
</div>

并在底部添加这个CSS块,在组件的关闭</div> 标签之前。

<style jsx global>{`
  .pell-container {
    border: 1px solid #ccc;
  }
  .pell,
  .pell-content {
    box-sizing: border-box;
  }
  .pell-content {
    height: 300px;
    outline: 0;
    overflow-y: auto;
    padding: 10px;
  }
  .pell-actionbar {
    background-color: #fff;
    border-bottom: 1px solid hsla(0, 0%, 4%, 0.1);
  }
  .pell-button {
    background-color: transparent;
    border: none;
    cursor: pointer;
    height: 30px;
    outline: 0;
    width: 30px;
    vertical-align: bottom;
    color: black;
  }
  .pell-button-selected {
    background-color: #f0f0f0;
  }
`}</style>

这就是最终的结果。

现在你应该可以保存房屋描述了。

解决XSS问题

现在进入第二部分--由使用dangerouslySetInnerHTML 引起的XSS漏洞。

我们如何解决这个问题呢?在后台,我们要将描述中的一些标签列入白名单,剔除所有其他标签。我将使用sanitize-html npm包

运行

npm install sanitize-html

现在在server.js ,我们在顶部添加这一行。

const sanitizeHtml = require('sanitize-html')

并在/api/host/edit/api/host/new 端点中使用Sequelize保存房子之前,我们添加。

houseData.description = sanitizeHtml(houseData.description, {
  allowedTags: [ 'b', 'i', 'em', 'strong', 'p', 'br' ]
})

这将清理描述并删除所有标签,除了我们特别允许的标签。

下一个部分。克隆Airbnb,上传房屋图片