org.springframework.web.util.HtmlUtils,特殊字符转义

特殊字符转义

由于 Web 应用程序需要联合使用到多种语言,每种语言都包含一些特殊的字符,对于动态语言或标签式的语言而言,如果需要动态构造语言的内容时,一个我们经常会碰到的问题就是特殊字符转义的问题。下面是 Web 开发者最常面对需要转义的特殊字符类型:

•HTML 特殊字符;
•JavaScript 特殊字符;
•SQL 特殊字符;
如果不对这些特殊字符进行转义处理,则不但可能破坏文档结构,还可以引发潜在的安全问题。Spring 为 HTML 和 JavaScript 特殊字符提供了转义操作工具类,它们分别是 HtmlUtils 和 JavaScriptUtils。

HTML 特殊字符转义

HTML 中 <,>,& 等字符有特殊含义,它们是 HTML 语言的保留字,因此不能直接使用。使用这些个字符时,应使用它们的转义序列:

•&:&
•" :"
•< :<
•> :>
由于 HTML 网页本身就是一个文本型结构化文档,如果直接将这些包含了 HTML 特殊字符的内容输出到网页中,极有可能破坏整个 HTML 文档的结构。所以,一般情况下需要对动态数据进行转义处理,使用转义序列表示 HTML 特殊字符。下面的 JSP 网页将一些变量动态输出到 HTML 网页中:


清单 1. 未进行 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 文档结构的动态数据进行转义处理。Spring 为我们提供了一个简单适用的 HTML 特殊字符转义工具类,它就是 HtmlUtils。下面,我们通过一个简单的例子了解 HtmlUtils 的具体用法:


清单 2. HtmpEscapeExample


package com.baobaotao.escape;
import org.springframework.web.util.HtmlUtils;
public class HtmpEscapeExample {
public static void main(String[] args) {
String specialStr = "<div id=\"testDiv\">test1;test2</div>";
String str1 = HtmlUtils.htmlEscape(specialStr); ①转换为HTML转义字符表示
System.out.println(str1);

String str2 = HtmlUtils.htmlEscapeDecimal(specialStr); ②转换为数据转义表示
System.out.println(str2);

String str3 = HtmlUtils.htmlEscapeHex(specialStr); ③转换为十六进制数据转义表示
System.out.println(str3);

④下面对转义后字符串进行反向操作
System.out.println(HtmlUtils.htmlUnescape(str1));
System.out.println(HtmlUtils.htmlUnescape(str2));
System.out.println(HtmlUtils.htmlUnescape(str3));
}
}



HTML 不但可以使用通用的转义序列表示 HTML 特殊字符,还可以使用以 # 为前缀的数字序列表示 HTML 特殊字符,它们在最终的显示效果上是一样的。HtmlUtils 提供了三个转义方法:

此外,HtmlUtils 还提供了一个能够将经过转义内容还原的方法:htmlUnescape(String input),它可以还原以上三种转义序列的内容。运行以上代码,您将可以看到以下的输出:


str1:<div id="testDiv">test1;test2</div>
str2:<div id="testDiv">test1;test2</div>
str3:<div id="testDiv">test1;test2</div>
<div id="testDiv">test1;test2</div>
<div id="testDiv">test1;test2</div>
<div id="testDiv">test1;test2</div>






/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.web.util;

/**
* Utility class for HTML escaping. Escapes and unescapes
* based on the W3C HTML 4.01 recommendation, handling
* character entity references.
*
* <p>Reference:
* <a href="http://www.w3.org/TR/html4/charset.html">http://www.w3.org/TR/html4/charset.html</a>
*
* <p>For a comprehensive set of String escaping utilities,
* consider Jakarta Commons Lang and its StringEscapeUtils class.
* We are not using that class here to avoid a runtime dependency
* on Commons Lang just for HTML escaping. Furthermore, Spring's
* HTML escaping is more flexible and 100% HTML 4.0 compliant.
*
* @author Juergen Hoeller
* @author Martin Kersten
* @since 01.03.2003
* @see org.apache.commons.lang.StringEscapeUtils
*/
public abstract class HtmlUtils {

/**
* Shared instance of pre-parsed HTML character entity references.
*/
private static final HtmlCharacterEntityReferences characterEntityReferences =
new HtmlCharacterEntityReferences();


/**
* 将 HTML 特殊字符转义为 HTML 通用转义序列;
* Turn special characters into HTML character references.
* Handles complete character set defined in HTML 4.01 recommendation.
* <p>Escapes all special characters to their corresponding
* entity reference (e.g. <code><</code>).
* <p>Reference:
* <a href="http://www.w3.org/TR/html4/sgml/entities.html">
* http://www.w3.org/TR/html4/sgml/entities.html
* </a>
* @param input the (unescaped) input string
* @return the escaped string
*/
public static String htmlEscape(String input) {
if (input == null) {
return null;
}
StringBuilder escaped = new StringBuilder(input.length() * 2);
for (int i = 0; i < input.length(); i++) {
char character = input.charAt(i);
String reference = characterEntityReferences.convertToReference(character);
if (reference != null) {
escaped.append(reference);
}
else {
escaped.append(character);
}
}
return escaped.toString();
}

/**
* 将 HTML 特殊字符转义为带 # 的十进制数据转义序列;
* Turn special characters into HTML character references.
* Handles complete character set defined in HTML 4.01 recommendation.
* <p>Escapes all special characters to their corresponding numeric
* reference in decimal format (&#<i>Decimal</i>;).
* <p>Reference:
* <a href="http://www.w3.org/TR/html4/sgml/entities.html">
* http://www.w3.org/TR/html4/sgml/entities.html
* </a>
* @param input the (unescaped) input string
* @return the escaped string
*/
public static String htmlEscapeDecimal(String input) {
if (input == null) {
return null;
}
StringBuilder escaped = new StringBuilder(input.length() * 2);
for (int i = 0; i < input.length(); i++) {
char character = input.charAt(i);
if (characterEntityReferences.isMappedToReference(character)) {
escaped.append(HtmlCharacterEntityReferences.DECIMAL_REFERENCE_START);
escaped.append((int) character);
escaped.append(HtmlCharacterEntityReferences.REFERENCE_END);
}
else {
escaped.append(character);
}
}
return escaped.toString();
}

/**
* 将 HTML 特殊字符转义为带 # 的十六进制数据转义序列;
* Turn special characters into HTML character references.
* Handles complete character set defined in HTML 4.01 recommendation.
* <p>Escapes all special characters to their corresponding numeric
* reference in hex format (&#x<i>Hex</i>;).
* <p>Reference:
* <a href="http://www.w3.org/TR/html4/sgml/entities.html">
* http://www.w3.org/TR/html4/sgml/entities.html
* </a>
* @param input the (unescaped) input string
* @return the escaped string
*/
public static String htmlEscapeHex(String input) {
if (input == null) {
return null;
}
StringBuilder escaped = new StringBuilder(input.length() * 2);
for (int i = 0; i < input.length(); i++) {
char character = input.charAt(i);
if (characterEntityReferences.isMappedToReference(character)) {
escaped.append(HtmlCharacterEntityReferences.HEX_REFERENCE_START);
escaped.append(Integer.toString((int) character, 16));
escaped.append(HtmlCharacterEntityReferences.REFERENCE_END);
}
else {
escaped.append(character);
}
}
return escaped.toString();
}

/**
* Turn HTML character references into their plain text UNICODE equivalent.
* <p>Handles complete character set defined in HTML 4.01 recommendation
* and all reference types (decimal, hex, and entity).
* <p>Correctly converts the following formats:
* <blockquote>
* &#<i>Entity</i>; - <i>(Example: &amp;) case sensitive</i>
* &#<i>Decimal</i>; - <i>(Example: &#68;)</i><br>
* &#x<i>Hex</i>; - <i>(Example: &#xE5;) case insensitive</i><br>
* </blockquote>
* Gracefully handles malformed character references by copying original
* characters as is when encountered.<p>
* <p>Reference:
* <a href="http://www.w3.org/TR/html4/sgml/entities.html">
* http://www.w3.org/TR/html4/sgml/entities.html
* </a>
* @param input the (escaped) input string
* @return the unescaped string
*/
public static String htmlUnescape(String input) {
if (input == null) {
return null;
}
return new HtmlCharacterEntityDecoder(characterEntityReferences, input).decode();
}

}




参考资料

学习

[url]http://www.ibm.com/developerworks/cn/java/j-lo-spring-utils2/[/url]
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值