深入理解URL编码和解码
- 2024-05-17 12:37:20
- 丁国栋
- 原创 113
我们经常在一些网站或者手册中见到“原义字符”、“转义字符”、“实体字符”等。它们是什么意思呢?
首先,我们要知道编码是将信息从一种形式或格式按照特定的规则转换为另一种。常见的URL、JSON、base64、ISO-8859-1(Latin 1)、UTF-8、unicode、GBK等,这都是编码规则,每一个规则都有相应的标准规范。而解码是编码的逆过程。
- 原义字符(literal characters)、普通字符等是指字符的字面意义、原来的意思、它的原意,即你看上去它是什么那它就是什么,例如你看上去$是个美元符号,那这里它就是个美元符号。
- 转义字符,转义字符是程序语言、数据格式和通信协议的形式文法的一部分,用于在字符串或字符序列中插入特殊字符,这些特殊字符在普通文本中可能没有定义或有特定含义。例如我们知道反斜线 (\) 是转义字符的基础,后接一个字符形成转义序列,用\$ 就可以表示$字面意义,用\n就可以表示换行符等。
- HTML 实体(HTML entities)、名称实体(named entities),这是指在HTML中为了用于表示特殊字符或不可打印字符的编码方式,这些特殊字符被编码成实体名称(如 < 或 >)或实体编号(如 < 或 >)。“ & < > ' " ”等这些字符在 HTML 中有特殊用处,如需保持原意,需要用 HTML 实体来表达。 被转换的实体有: &(&符号(读and符)), "(双引号) , '(单引号) , < (英文左尖括号、小于号)以及>(英文右尖括号、大于号)。
以下内容适用于PHP,列举了与编码和实体相关的部分函数。
- get_html_translation_table() 返回使用 htmlspecialchars() 和 htmlentities() 后的转换表,这个函数实际没什么用,也很少用。
- htmlspecialchars() 将特殊字符转换为 HTML 实体,例如你要将一个URL打印出来,那就应该使用该函数将URL中的特殊字符转成HTML实体。在htmlA标签中,href的内容必须使用实体字符,即需要使用htmlspecialchars将"http://host/?x=1&y=2"转换成“http://host/?x=1&y=2”
- htmlspecialchars_decode() 将特殊的 HTML 实体转换回普通字符
- htmlentities() 将字符转换为 HTML 转义字符,比如将&转换成&,但注意它并不会将空格转换成
- html_entity_decode() 将HTML 转义字符转换为原意字符字符,它可以将 转换成空格
- urlencode() 编码 URL 字符串,注意“+”plus加号会编码为空格(历史原因),此编码与 WWW 表单 POST 数据的编码方式是一样的,同时与 application/x-www-form-urlencoded 的媒体类型编码方式一样。
- rawurlencode() - 按照 RFC 3986 对 URL 进行编码 URL-encode according to RFC 3986。
- rawurldecode() 对已编码的 URL 字符串进行解码。它不会把加号('+')解码为空格,而 urldecode() 会将加号解码成空格。因此当原始内容中出现了加号这样的字符时,应该使用rawurlencode编码再用rawurldecode解码。
PHP函数中rawurlencode 和 urlencode有什么区别?
在PHP中,urlencode()和rawurlencode()函数的主要区别在于它们对空格和非标准URL字符的编码方式。
urlencode()函数将所有非字母数字字符(除了连字符、下划线和点)替换为百分比符号(%)后跟两个十六进制数字,并将空格编码为加号(+)。这个编码方式与WWW表单提交的数据编码相同,即application/x-www-form-urlencoded媒体类型。历史原因导致空格被编码为加号(+),而不是百分比编码(%20)。
rawurlencode()函数则按照RFC 3986标准,将所有非字母数字字符(除了连字符、下划线、波浪线和点)替换为百分比符号(%)后跟两个十六进制数字。这个编码方式保护URL中的字面字符不被解释为特殊的URL分隔符,并且保护URL不受传输媒介(如某些邮件系统)的字符转换影响。因此,rawurlencode()将空格编码为百分比编码(%20),而不是加号(+)。
假设现在有字符串 'https://www.google.com/search?q=%E4%BD%A0%E5%A5%BD+%E4%B8%AD%E5%9B%BD',urldecode 会将其转换成'https://www.google.com/search?q=你好 中国',而rawurldecode会转换成 'https://www.google.com/search?q=你好+中国'。由此可见,此时应该使用rawurldecode保留加号。
现在来看这个问题,在数据库里应该存原始字符还是转义字符呢?
在数据库中保存HTML代码时,最佳实践是直接存储原始HTML代码,而不是转义字符。这是因为HTML标签和特殊字符在HTML文档中具有特定的含义,如果你对这些字符进行转义,那么当这些数据被渲染到网页上时,可能无法正确显示或者执行预期的功能。
安全考虑:虽然直接存储原始HTML代码更为方便,但在处理用户输入的HTML代码时,应采取适当的安全措施,如使用HTML过滤库或白名单策略,以防止XSS攻击。使用参数化查询:在构建SQL语句时,尽量使用参数化查询来避免SQL注入攻击,这对于任何类型的数据输入都是好的做法。