您当前的位置:首页 > 文章 > HTML实体编码

HTML实体编码

作者:aleave 时间:2023-05-22 阅读数:393 人阅读


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("&lt;img src=@ οnerrοr=alert(123) /&gt;")

  • 可以发现div不会执行代码,textarea也不会,都只是显示一样的文本
<img src=@ οnerrοr=alert(123) />
  • 所以结论就是前端输入和输出的内容,如果需要复制给HTML标签且不经过HTML实体编码,那么会不安全

HTML实体编码介绍

  • 通过上面的例子,我们可以知道,某些保留字符出现在文本节点和标签值里是不安全的

  • 在XHTML中,这些保留字符出现在标签里会立刻报错,但是HTML解析器太懒了,容错性大,并不会出现语法报错

  • 要想安全的使用<,&,>,"等字符,就需要使用一套实体编码(entity encoding)的简单编码策略

  • 这套HTML实体编码策略是以&符号开头,以;分号结尾的

  • 在XML中只有少数几个这种编码,而在HTML中,存在数百个这种实体编码,并且常用的浏览器都支持这种用法

HTML编码有以下几种方式

  1. HTML实体编码,格式以&符号开头,以;分号结尾的
  • HTML实体编码参考手册
<textarea name="" id="textarea" cols="30" rows="10">     &lt;img src=&quot;localhost&quot;&gt;   </textarea> 
  • 结果是:
<img src="localhost">
  1. 十进制的ASCLL编码,格式:以符号&#开头,分号;结尾
  • ascll编码对照表
<textarea name="" id="textarea" cols="30" rows="10">     &#60;&#105;mg src&#61;"localhost"&#62;   </textarea> 
  • 结果是:
<img src="localhost">
  1. Unicode字符编码,格式:以符号&#开头,分号;结尾
  • 另外,下面的unicode编码参考表的数字对应的是十六进制的,但是我们需要先转换为十进制再显示!
  • unicode编码参考
  • 首先把0022转换为十进制是0034;003D转换为十进制是0061
  <textarea name="" id="textarea" cols="30" rows="10">     <img src&#0061;&#0034;localhost&#0034;>   </textarea> 
  • 结果是:
<img src="localhost">

  1. 十六进制的ascll码,格式:以&#x开头,分号;结尾
  • 参考上面的ascll表,但是注意需要先转换为十六进制。
<textarea name="" id="textarea" cols="30" rows="10">     <img src&#x3D;&#x0022;localhost&#x0022;>   </textarea> 
  • 结果是:
<img src="localhost">

  • 最后综合几种写法看看
  <textarea name="" id="textarea" cols="30" rows="10">     &lt;&#64;&#0033;&#x3c;&gt;   </textarea> 
  • 最后在textarea中显示
<@!<>
  • 也就是<被解析为"<";&#64被解析为"@";&#0033被解析为"!";&#x3c被解析为"<";>被解析为">"

HTML实体编码使用

  1. 使用在标签的双引号内部
 <img src="https://wangbase.com/blogimg/asset/202107/bg2021072117.png">     
<img src="&#104;ttps://wangbase.com/blogimg/asset/202107/bg2021072117.png"> 
  • 我们可以发现,两种写法都可以加载到图片!
  1. 写在标签的属性中
    <img sr&#99;="https://wangbase.com/blogimg/asset/202107/bg2021072117.png"> 

  • 写在标签属性中,相当于破坏了标签的属性值,所以不会加载图片!
  1. 作为双引号,等于号
    <img src&#x3D;"https://wangbase.com/blogimg/asset/202107/bg2021072117.png"> 
<img src=&#x22;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('&lt;img src=@ οnerrοr=alert(123) /&gt;'
// <img src=@ οnerrοr=alert(123) /> 
console.log('&lt;img src=@ οnerrοr=alert(123) /&gt;'
// &lt;img src=@ οnerrοr=alert(123) /&gt; 
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的预留标签,可能会被误解析。这时就需要将小于号和大于号写成字符实体:
小于号这样写:&lt; 或 &#60;
大于号这样写:&gt; 或 &#62;
前面的写法称为实体名称,后面的写法则是实体编号。ISO-8859-1字符集(西欧语言)中两百多个字符设定了实体名称,而对于其它所有字符都可以用实体编号来代替。
2、网页编码采用了特定语言的编码,却需要显示来自其它语言的字符。例如,网页编码采用了西欧语言ISO-8859-1,却要在网页中显示中文,这时必须将中文字符以实体形式写入HTML代码中。

本页面字符实体编号采用Unicode标准。


参考:https://cloud.tencent.com/developer/article/1728791



本站大部分文章、数据、图片均来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了您的权益请来信告知我们删除。邮箱:1451803763@qq.com