Web开发中特殊字符编码的那些事
在Web开发中,常常会遇到因为特殊字符编码的问题,引发的安全问题,或是数据正确性的问题。特总结一下:
HTML编码
HTML 中 &、"、<、>等字符有特殊含义,它们是 HTML 语言的保留字,因此不能直接使用。使用这些个字符时,应使用它们的转义序列:
&:& " :" ' : ' < :< > :>
由于 HTML 网页本身就是一个文本型结构化文档,如果直接将这些包含了 HTML 特殊字符的内容输出到网页中,极有可能破坏整个 HTML 文档的结构。所以,一般情况下需要对动态数据进行转义处理,使用转义序列表示 HTML 特殊字符。下面的 JSP 网页将一些变量动态输出到 HTML 网页中:
<%@ page language="java" contentType="text/html; charset=utf-8"%> <%! String userName = "</td><tr></table>"; String address = " " type="button"; %> <table border="1"> <tr> <td>姓名:</td><td><%=userName%></td> ① </tr> <tr> <td>年龄:</td><td>28</td> </tr> </table> <input value="<%=address%>" type="text" /> ②
在 ① 和 ② 处,我们未经任何转义处理就直接将变量输出到 HTML 网页中,由于这些变量可能包含一些特殊的 HTML 的字符,它们将可能破坏整个 HTML 文档的结构。我们可以从以上 JSP 页面的一个具体输出中了解这一问题:
<table border="1"> <tr> <td>姓名:</td><td></td><tr></table></td> ① 破坏了 <table> 的结构 </tr> <tr> <td>年龄:</td><td>28</td> </tr> </table> <input value=" " type="button" type="text" /> ② 将本来是输入框组件偷梁换柱为按钮组件
融合动态数据后的 HTML 网页已经面目全非,首先 ① 处的 <table> 结构被包含 HTML 特殊字符的 userName 变量截断了,造成其后的 <table> 代码变成无效的内容;其次,② 处 <input> 被动态数据改换为按钮类型的组件(type="button")。为了避免这一问题,我们需要事先对可能破坏 HTML 文档结构的动态数据进行转义处理。
由于 HTML 网页本身就是一个文本型结构化文档,如果直接将这些包含了 HTML 特殊字符的内容输出到网页中,极有可能破坏整个 HTML 文档的结构。所以,一般情况下需要对动态数据进行转义处理,使用转义序列表示 HTML 特殊字符。
JavaScript涉及的特殊编码
单、双引号、控制字符(制表符(tab), 反斜线(backslash), 换行(cr), 换页符(ff), etc.)
SQL特殊字符的注入
保证不要将SQL中的参数通过拼字符串的方式,就可以避免SQL注入的相关问题
常用方法:
Java端编码方法:
org.apache.commons.lang3.StringEscapeUtils
escapeEcmaScript
escapeHtml4
JavaScript端解码方法:
var decodeEntities = (function() { // this prevents any overhead from creating the object each time var element = document.createElement('div'); function decodeHTMLEntities (str) { if(str && typeof str === 'string') { // strip script/html tags str = str.replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, ''); str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, ''); element.innerHTML = str; str = element.textContent; element.textContent = ''; } return str; } return decodeHTMLEntities; })(); var s = decodeEntities("<script>&'");
Underscore.js的unescape方法
最简单的JS方法
function htmlDecode(str) { var s = ""; if (str.length == 0) return ""; s = str.replace(/&/g, "&"); s = s.replace(/</g, "<"); s = s.replace(/>/g, ">"); s = s.replace(/'/g, "\'"); s = s.replace(/"/g, "\""); return s; }
URL编码
当一个字符串需要作为跳转的URL地址或是URL中包含的参数时,如果包含以下特殊字符,就需要做URL编码:
Dollar ("$")
Ampersand ("&")
Plus ("+")
Comma (",")
Forward slash/Virgule ("/")
Colon (":")
Semi-colon (";")
Equals ("=")
Question mark ("?")
'At' symbol ("@")
Space
Quotation marks
'Less Than' symbol ("<")
'Greater Than' symbol (">")
'Pound' character ("#")
Percent character ("%")
Left Curly Brace ("{")
Right Curly Brace ("}")
Vertical Bar/Pipe ("|")
Backslash ("\")
Caret ("^")
Tilde ("~")
Left Square Bracket ("[")
Right Square Bracket ("]")
Grave Accent ("`")
具体情况如下:
字符串是作为URL跳转的用encodeURI
字符串是作为URL的一个参数时,使用encodeURIComponent
到了Java后台时,就需要对解析的参数调用:
URLDecoder.decode(param,"utf-8");