背景
假设有个留言版程序已经上线并正常运作中,但是现在发现,有些用户会在留言中输入一些HTML标签。基于安全性的考量,不希望用户输入的HTML标签直接出现在留言中而被浏览器当作HTML的一部分。例如,并不希望用户在留言中输入com.sina.com.cn这样的信息,你不想信息在留言显示中直接变成超链接,让用户有机会在留言版中打广告,希望将一些HTML过滤掉,如将<、>角括号置换为HTML实体字符<与>。
使用<、>角括号与<与>的区别:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <a href="www.baidu.com">点击我</a><br> <a href="www.baidu.com">点击我</a> </body> </html>
上面的html文件直接使用浏览器打开后如下所示:
点击我
<a href="www.baidu.com">点击我</a>
实现分析
1、使用过滤器来过滤请求参数。
2、但虽然可以使用HttpServletRequest的getParameter()取得请求参数值,但就是没有一个像setParameter()的方法,可以将处理过后的请求参数重新设置给HttpServletRequest。你也许会想要亲自实现HttpServletRequest接口,让getParameter()返回过滤后的请求参数值,但这么做的话,HttpServletRequest接口定义的方法都要实现,实现所有方法非常麻烦。所幸,有个HttpServletRequestWrapper帮忙实现了HttpServletRequest接口,只要继承HttpServletRequestWrapper类,并编写想要重新定义的方法即可。相对应于ServletRequest接口,也有个ServletRequestWrapper类可以使用。
代码实现
1、添加jar包,这里直接使用Apache Commons Lang包中的方法来实现替换字符。
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.4</version> </dependency>
2、请求封装器
package com.test; import org.apache.commons.lang3.StringEscapeUtils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; public class MyRequestWrapper extends HttpServletRequestWrapper { // 构造方法不可少,且在方法内部必须调用父类的构造方法 public MyRequestWrapper(HttpServletRequest request) { super(request); } @Override public String getParameter(String name) { String parameter = getRequest().getParameter(name); // 使用Apache Commons Lang程序库中StringEscapeUtils类提供的escapeHtml()方法来进行字符替换 return StringEscapeUtils.escapeHtml3(parameter); } }
代码中定义了一个接受HttpServletRequest的构造器,真正的HttpServletRequest将通过此构造器传入,必须使用super(request)调用父类(装饰类)的构造方法,父类(装饰类)会将它赋值给一个成员变量。之后如果要取得被封装的HttpServletRequest,则可以调用getRequest()方法。
String parameter = getRequest().getParameter(name); // 被装饰对象,即原始的请求对象的方法被调用。
return StringEscapeUtils.escapeHtml3(parameter); // 添加新功能
3、拦截器
package com.test; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebFilter("/*") public class RequestStringFilter implements Filter { private FilterConfig filterConfig; @Override public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; MyRequestWrapper myRequestWrapper = new MyRequestWrapper(request); chain.doFilter(myRequestWrapper, response); } public void destroy() { } }
4、页面
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="hello" method="post"> <textarea rows="5" cols="100" name="message"></textarea><br> <input type="submit" value="提交"> </form> </body> </html>
5、servlet
package com.test; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebServlet(urlPatterns = "/hello") public class MyServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { request.setCharacterEncoding("UTF-8"); String message = request.getParameter("message"); response.setContentType("text/html"); response.setCharacterEncoding("UTF-8"); PrintWriter writer = response.getWriter(); writer.println("<!DOCTYPE html>"); writer.println("<html>"); writer.println("<head>"); writer.println("<meta charset="UTF-8">"); writer.println("<title>Title</title>"); writer.println("</head>"); writer.println("<body>"); writer.print(message); writer.println("</body>"); writer.println("</html>"); writer.close(); } }
测试方法
1、访问页面 http://127.0.0.1/index.html
2、在页面中的大文本框输入:<a href="www.baidu.com">点击我</a>
3、点击提交