HTML实体编码
HTML实体编码
- 首先通过一个例子来说明一下HTML实体编码的重要性
// 前端 <!DOCTYPE html> <html lang="en"> <meta charset="utf8" /> <head> <title>测试</title> <style></style> </head> <body> <div id="test"></div> <textarea name="" id="textarea" cols="30" rows="10"></textarea> <input type="button" onclick="submit()" value="提交"> <script> function submit(){ let test = document.getElementById("test"); fetch("http://localhost:3000").then((res)=>{ res.text().then((response)=>{ test.innerHTML=response; }); }); } </script> </body> </html>
// node.js后端 const http = require('http') const fs = require('fs') const path = require('path') const port = 3000; const server =http.createServer((req,res)=>{ res.statusCode = 200 let arr=['http://localhost:63342','http://localhost:3001'] if(arr.includes(req.headers.origin)){ res.setHeader('Cache-Control','no-cache') res.setHeader('Connection','keep-alive') res.setHeader('Access-Control-Allow-Origin',req.headers.origin) // req.headers.origin res.setHeader('Access-Control-Allow-Credentials', 'true') } res.end("<img src=@ οnerrοr=alert(123) />") }) server.listen(port,()=>{ console.log('start') })
-
然后可以发现,把后端响应的值赋值给textarea,只会在textarea显示对应的文本,并不会执行
-
然后把对应的响应内容赋值给div,就可以执行代码,弹出弹窗,不安全!
-
但是我们把后端返回的内容修改一下,改为使用HTML实体编码
res.end("<img src=@ οnerrοr=alert(123) />")
- 可以发现div不会执行代码,textarea也不会,都只是显示一样的文本
<img src=@ οnerrοr=alert(123) />
- 所以结论就是前端输入和输出的内容,如果需要复制给HTML标签且不经过HTML实体编码,那么会不安全
HTML实体编码介绍
-
通过上面的例子,我们可以知道,某些保留字符出现在文本节点和标签值里是不安全的
-
在XHTML中,这些保留字符出现在标签里会立刻报错,但是HTML解析器太懒了,容错性大,并不会出现语法报错
-
要想安全的使用<,&,>,"等字符,就需要使用一套实体编码(entity encoding)的简单编码策略
-
这套HTML实体编码策略是以&符号开头,以;分号结尾的
-
在XML中只有少数几个这种编码,而在HTML中,存在数百个这种实体编码,并且常用的浏览器都支持这种用法
HTML编码有以下几种方式
- HTML实体编码,格式以&符号开头,以;分号结尾的
- HTML实体编码参考手册
<textarea name="" id="textarea" cols="30" rows="10"> <img src="localhost"> </textarea>
- 结果是:
<img src="localhost">
- 十进制的ASCLL编码,格式:以符号&#开头,分号;结尾
- ascll编码对照表
<textarea name="" id="textarea" cols="30" rows="10"> <img src="localhost"> </textarea>
- 结果是:
<img src="localhost">
- Unicode字符编码,格式:以符号&#开头,分号;结尾
- 另外,下面的unicode编码参考表的数字对应的是十六进制的,但是我们需要先转换为十进制再显示!
- unicode编码参考
- 首先把0022转换为十进制是0034;003D转换为十进制是0061
<textarea name="" id="textarea" cols="30" rows="10"> <img src="localhost"> </textarea>
- 结果是:
<img src="localhost">
- 十六进制的ascll码,格式:以&#x开头,分号;结尾
- 参考上面的ascll表,但是注意需要先转换为十六进制。
<textarea name="" id="textarea" cols="30" rows="10"> <img src="localhost"> </textarea>
- 结果是:
<img src="localhost">
- 最后综合几种写法看看
<textarea name="" id="textarea" cols="30" rows="10"> <@!<> </textarea>
- 最后在textarea中显示
<@!<>
- 也就是<被解析为"<";@被解析为"@";!被解析为"!";<被解析为"<";>被解析为">"
HTML实体编码使用
- 使用在标签的双引号内部
<img src="https://wangbase.com/blogimg/asset/202107/bg2021072117.png">
<img src="https://wangbase.com/blogimg/asset/202107/bg2021072117.png">
- 我们可以发现,两种写法都可以加载到图片!
- 写在标签的属性中
<img src="https://wangbase.com/blogimg/asset/202107/bg2021072117.png">
- 写在标签属性中,相当于破坏了标签的属性值,所以不会加载图片!
- 作为双引号,等于号
<img src="https://wangbase.com/blogimg/asset/202107/bg2021072117.png">
<img src="https://wangbase.com/blogimg/asset/202107/bg2021072117.png">
- 作为等于号,导致浏览器识别为属性名称未结束,错误。不会加载图片
- 作为等双引号,结果被识别为:(左边两个双引号)""https://wangbase.com/blogimg/asset/202107/bg2021072117.png"
HTML实体编码不可用于javascript
- HTML实体编码的范围是HTML文档,不包括javscript执行环境,因为javascript执行环境的解析器不是HTML解析器!
- 接下来看个代码
document.write('<img src=@ οnerrοr=alert(123) />')
// <img src=@ οnerrοr=alert(123) />
console.log('<img src=@ οnerrοr=alert(123) />')
// <img src=@ οnerrοr=alert(123) />
console.log('\<img src=@ οnerrοr=alert(123) \/\>')
// <img src=@ οnerrοr=alert(123) />_
- 1. document.write由于最后的字符串被输出到html页面,所以还是会被html实体解码为对应标签
- 2. 由于只是在js环境中打印,所以最后没有进行html实体编码,字符串不变
- 3. 由于js的自解码机制会对纯转义字符添加反斜号,所以最后被解析为没有反斜号的形式
微信公众号:web前端进阶之路
其他参考:https://www.qqxiuzi.cn/bianma/zifushiti.php
字符实体是用一个编号写入HTML代码中来代替一个字符,在使用浏览器访问网页时会将这个编号解析还原为字符以供阅读。
这么做的目的主要有两个:
1、解决HTML代码编写中的一些问题。例如需要在网页上显示小于号(<)和大于号(>),由于它们是HTML的预留标签,可能会被误解析。这时就需要将小于号和大于号写成字符实体:
小于号这样写:< 或 <
大于号这样写:> 或 >
前面的写法称为实体名称,后面的写法则是实体编号。ISO-8859-1字符集(西欧语言)中两百多个字符设定了实体名称,而对于其它所有字符都可以用实体编号来代替。
2、网页编码采用了特定语言的编码,却需要显示来自其它语言的字符。例如,网页编码采用了西欧语言ISO-8859-1,却要在网页中显示中文,这时必须将中文字符以实体形式写入HTML代码中。
本页面字符实体编号采用Unicode标准。
参考:https://cloud.tencent.com/developer/article/1728791
本站大部分文章、数据、图片均来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了您的权益请来信告知我们删除。邮箱:1451803763@qq.com