这篇文章是一个新系列的一部分,我们用Next.js建立一个克隆的Airbnb。请看第一篇文章。
- 第一部分。让我们从安装Next.js开始
- 第2部分:建立房屋列表
- 第3部分:建立房屋详细视图
- 第4部分:CSS和导航栏
- 第5部分:从日期选择器开始
- 第6部分:添加侧边栏
- 第7部分:添加 react-day-picker
- 第8部分。在页面中添加日历
- 第9部分:配置DayPickerInput组件
- 第10部分:同步开始和结束日期
- 第11部分:显示所选日期的价格
- 第12部分:登录和注册表格
- 第13部分:激活模态
- 第14部分:发送注册数据到服务器
- 第15部分:添加postgres
- 第16部分:实现模型和DB连接
- 第17部分:创建一个会话令牌
- 第18部分:实现登录
- 第19部分:确定我们是否已经登录了
- 第20部分:在我们登录后改变状态
- 第21部分:注册后登录
- 第22部分:创建模型并将数据移到数据库中
- 第23部分:使用数据库而不是文件
- 第24部分:处理预订
- 第25部分:处理预订的日期
- 第26部分:如果已经预订了,则防止预订
- 第27部分:添加Stripe进行支付
- 第28部分:克隆Airbnb,处理Stripe webhooks
- 第29部分:克隆的Airbnb,查看预订情况
- 第30部分:克隆的Airbnb,清理预订
- 第31部分:克隆的Airbnb,管理房屋
- 第32部分:复制的Airbnb,添加新房子
- 第33部分:克隆的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,上传房屋图片