为啥在知乎编辑框里正确处理字符转义如此困难
我们现在讨论的这个问题和嵌入 code 一点关系都没有。如果支持嵌入 code,无非就是可以让部分内容用等宽字体显示,或者再高级一点,能支持个关键字高亮,那些功能如果能有当然能好,但是现阶段其实并不着急,而且正如你们所说的,“众口难调”,所以这些高级功能,的确是不那么迫切需要的。而我现在一直对团队穷追不舍的,仅仅是最最基本的功能:让编辑器能够原样还原用户的输入。我们现在要讨论的也不是什么“更好的处理实现方法”,而是正确的处理实现方法。如果连正确都没有保障的话,“更好”根本无从谈起。@马骁 给出的解释是要支持富文本,并且保证安全和性能,这个解释我完全不认同。我们先看一下用户输入的大于小于号是如何到达的吧:1. 用户在高级编辑器里输入了一段文字。由于编辑器支持富文本,因此编辑器会在客户端用 HTML 格式对所有输入内容进行编码。此时,我们输入的所有特殊符号,譬如我们前面提到的大于小于号,在客户端就已经正确地编码成 entity 了,也就是说,此时的大于小于号已经分别是 \u0026amp;gt; 和 \u0026amp;lt; 这样的形式了。2. 用户点击了“提交”按钮,此时,浏览器发起了一个 AJAX 请求,以 POST 的方式对服务器提交数据。此时,浏览器把已经正确进行过 entity 转义的内容用 URL Encoded 格式进行编码。此时的大于小于号在前往服务器的途中是这样的格式:%26gt%3B 和 %26lt%3B%。3. 服务端收到客户端发来的请求后,对数据进行 URL Decode 解码,解码完毕后大于小于号变回 \u0026amp;gt; 和 \u0026amp;lt; 这样的形式。那我们需要怎么样才能让用户原样看到之前输入的大于小于号呢?答案是,为了让用户能看到这两个符号,我们必须以 entity 的方式输出给用户,也就是说,我们需要返回给用户 \u0026amp;gt; 和 \u0026amp;lt; 这样的形式才行。既然服务器拿到的数据已经是这样的形式了,因此,为了让用户能够正常看到,我们对于这部分内容应该做的事情就是让它保持原样就好。从上面的步骤可以看出,从第 1 步到第 3 步,大于小于号都得到了正确的编码,整个传递过程也是没有问题的。而且,由于大于小于号已经被编码了,因此用户输入的大于小于号是不会对服务器造成任何伤害的。那么,什么样的东西是有可能造成损害的呢?答案是,没有被编码过的真正的大于小于号。我们已经说了,用户输入的大于小于号都会被编辑器自动转义成 entity,那么,为什么会存在“真正的”大于小于号呢?那是因为,我们的高级编辑器是支持格式的,当用户设置了格式,譬如说用户选择了加粗、倾斜的时候,高级编辑器就会插入一些 HTML 代码来实现这些效果。另外,用户输入的回车,在高级编辑器里其实也是通过 HTML 标签来实现的。这些 HTML 代码在提交的时候会以“真正的大于小于号”的形式发送出去,这和用户自己输入的大于小于号是完全不一样的。为什么这些“真正的大于小于号”是可能有害的呢?那是因为,通过这些“真正的大于小于号”,我们不仅仅可以对文字设置格式,我们还可以创建一些特殊的标签,把一些恶意的脚本引入到答案里面来,对其它浏览答案的人造成损害。虽然我们通过内置的高级编辑器是无法创建这样的恶意代码的,可是,坏人显然是可以绕过上面说的第 1 步、第 2 步,直接对服务器提交专门构造出来的恶意数据给第 3 步的,不是么?因此,在收到第 3 步数据的时候,就必须对数据进行“消毒”处理了。消毒的过程稍微有点小复杂,不过原理其实很简单:既然真正的大于小于号是罪魁祸首,那我们就需要对所有出现真正的大于小于号的地方严加防范,所有出现这些真正大于小于号的地方,我们都必须仔细地检查一下,看看有没有出现不是我们的编辑器构造出来的非法标签,如果有的话,就把所有的非法标签都消灭掉就可以了。总而言之,为了保证大家的安全,我们所要做的事情就是,严加防范所有的“真正的大于小于号”,而对于用户输入的大于小于号,由于它们已经被编码成 \u0026amp;gt; 和 \u0026amp;lt; 这样的形式了,因此它们不属于“真正的大于小于号”,因此我们是完全不需要考虑它们的。可是,我一直不理解的一点就是,在拿到正确编码的数据之后,对它又进行了一次 entity 解码,这下可不得了,已经正确编码的 \u0026amp;gt; 和 \u0026amp;lt; 又重新变回了“真正的大于小于号”,和之前的别的真正的大于小于号全混在一起了。这下服务器可如临大敌了,为了保证大家的安全,只好再暴力干涉一次,干脆把所有的小于号之后的内容全给删了得了。于是,大家就发现,我怎么打不出这个符号了:~~~ \u0026gt; _ \u0026lt; ~~~~可是,为什么呢?为什么要这么做呢?为什么要把已经正确编码的大于小于号又做一次不必要的解码呢?我不知道……你们知道么?我们还是把这个问题交给团队来回答吧,也许他们能告诉我们为什么要这么做。以上说的是回答的编辑框里发生的情况。对于评论框,情况可就简单太多了:由于评论框不支持格式,只支持纯文本,因此评论是完全不存在“编码过的大于小于号”和“真正的大于小于号”这两个东西的区别的,事实上,评论里面存在的大于小于号,全部都没有经过编码。那大家也许会问了,全都没编码,那不是很危险么?不,当然不是,全都没编码的话,那我们拿到数据之后,就对它们统一做一次全部编码就好了,完全没有前面说的“编码过的大于小于”和“没有编码过的大于小于”混合在一起的这种困扰。编码非常简单,就是一个查找替换就行了,把所有的特殊符号都用 entity 来代替。全部编码之后,文本里面就不可能再出现任何“坏”的大于小于号了,因此我们没有必要对它再做任何额外的消毒处理,比前面的情况还简单。那么,为什么团队不那么做,却要要把所有评论里的小于号之后的内容也全给删了呢?为什么呢?为什么要这么做呢?我不知道……你们知道么?我们还是把这个问题交给团队来回答吧,也许他们能告诉我们为什么要这么做。
■网友
推荐阅读
- 为啥看到书柜上的藏书会有心旷神怡的感觉
- 为啥知乎上普便有一种【我在北上广深打工,所以拥有更好的视野】这样的错觉
- 为啥工商银行的用户体验如此之差
- 汽车|看了中消协4S店服务测评调查结果,终于知道法系车为啥卖不好了
- 你为啥从窝窝商城离职?
- 知乎有没有必要增加一个特别关注功能
- 为啥5G和2.4G默认的BSSID是相同的
- 为啥电器实体店的价格比淘宝贵那么多
- 现在在线学习视频有很多了,为啥大部分人还是喜欢下载下来观看
- 为啥到现在你还没有女朋友 ?
