当我们在做web应用的时候都会处理客户端提交到服务器的数据,如去除前后空格,一些非常字符,SQL注入类似的东西,在这里我主要说前后空格我是怎么来解决的,其它也都可以照此方法快速、方便、有效的解决,但是我一般对于非法字符,都是采用了标签来解决它的,并没有使用Filter转义掉(纯属个人解决办法)。
去除前后空格看似非常简单的事,但是有许多人可能就是因为这一个小问题,折磨自己半天,客户端提交到所有的东西,都是以字符串形式提交的,我们不知道客户是怎么操作的,他可能把一个age属性对应的值,在输入时多加了一个空格,而服务器age对应的却是Integer类型,如果你使用servlet这事也好解决,但是如果你使用的是MVC框架,自动封装时就会得到一个类型转换异常,然而这个时候你是否有好的解决办法呢?
这里我使用Filter来解决这一问题,这是最简单方便有效的解决方式,因为你不需要对每一个属性在封装前都去trim(),因为这是一件非常乏味的事情。大家都知道filter可以过滤我们想要它过滤的每一个请求,在这请求中有HttpServletRequest、HttpServletResponse。我们知道服务器取得客户端发送的参数都是通过HttpServletRequest来获取的,那我们可不可以在使用HttpServletRequest取值的时候就为每一个客户端提交的属性去除前后空格,或者其它的一些过滤操作。这肯定是可以的,那我们先来了解一下服务器是怎么取得客户端的值的。
1.getParameter(name),返回单个值。
2.getParameterValues(name),返回一个数组。
3.getParameterMap(),把客户端提交参数封装为一个Map返回。K:name,V:value。
当我们使用servlet的时候一般都是使用前两种,struts1使用的第2种,struts2(xwork)则使用的第3种,那么我们只要在这三个方法调用的时候处理前后空格,那么返回到服务器的参数就又减少了一分出bug的机会,看下面的实现。
public class RequestParameterFilter implements Filter {
private static Log log = LogFactory.getLog(RequestParameterFilter.class);
private List<String> excludeNames;
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//
request = new HttpServletRequestWrapper2((HttpServletRequest) request);
chain.doFilter(request, response);
}
public void init(FilterConfig config) throws ServletException {
String exclude = config.getInitParameter("exclude");
// not is null.
if (exclude != null && exclude.length() > 0) {
excludeNames = Arrays.asList(exclude.split(","));
if (log.isDebugEnabled()) {
log.debug("initialize arguments.");
}
}
}
/**
* 该类继承之HttpServletRequestWrapper,并重写了对应取得客户端相当参数值的所有的方法。
* <ul>
* <li>getParameter</li>
* <li>getParameterValues</li>
* <li>getParameterMap</li>
* </ul>
*
* @version 1.0/2010-6-10 上午11:25:47
* @author Aidan
* @see HttpServletRequestWrapper
*/
private class HttpServletRequestWrapper2 extends HttpServletRequestWrapper {
private ParameterMap2 pm2;
public HttpServletRequestWrapper2(HttpServletRequest request) {
super(request);
}
public String getParameter(String name) {
if (excludeNames != null && excludeNames.contains(name)) {
return super.getParameter(name);
}
return trim(super.getParameter(name));
}
@SuppressWarnings("unchecked")
public Map getParameterMap() {
// xwork便使用此方法取值
// 该方法返回一个Map,Map映射了客户端请求对应的键值(K,V)。
if (pm2 == null) {
pm2 = new ParameterMap2(super.getParameterMap());
}
return pm2;
}
public String[] getParameterValues(String name) {
// Struts1使用此方法取得所有的参数值
if (excludeNames != null && excludeNames.contains(name)) {
return super.getParameterValues(name);
}
return (String[]) trim(super.getParameterValues(name));
}
}
/**
* 该此继承自HashMap。
*
* @version 1.0/2010-6-10 上午11:30:13
* @author Aidan
* @see HashMap
*/
@SuppressWarnings( { "unchecked", "serial" })
private class ParameterMap2 extends HashMap {
private Set entrySet;
/**
* 若要构造此类对象,则需要传入一个map参数,该map对应的客户端请求的参数(K,V)。
*
* @param map
* 映射客户端参数。
*/
public ParameterMap2(Map map) {
super(map);
}
public Set entrySet() {
// xwork使用了此方法取值
if (entrySet == null) {
entrySet = new HashSet();
Set temSet = super.entrySet();
for (Iterator iterator = temSet.iterator(); iterator.hasNext();) {
Map.Entry me = (Map.Entry) iterator.next();
Entry2 entry = new Entry2(me);
entrySet.add(entry);
}
}
return entrySet;
}
// 若直接从map使用key取得
public Object get(Object key) {
Object value = super.get(key);
// 不过滤此对象
if (excludeNames != null && excludeNames.contains(key)) {
return value;
}
if (value != null) {
return trim(value);
}
return null;
}
}
@SuppressWarnings("unchecked")
private class Entry2<K, V> implements Map.Entry<K, V> {
private Map.Entry me;
private boolean isTrim = true;
public Entry2(Map.Entry me) {
if (me == null) {
throw new IllegalArgumentException(
"Map.Entiry argument not null.");
}
this.me = me;
// 不过滤此对象
if (excludeNames != null && excludeNames.contains(me.getKey())) {
isTrim = false;
}
}
public K getKey() {
return (K) me.getKey();
}
public V getValue() {
if (isTrim) {
return (V) trim(me.getValue());
}
return (V) me.getValue();
}
public V setValue(V value) {
return (V) me.setValue(value);
}
}
/**
* 去除一个Object类型对应的前后空格,因为客户端提交参数有两种,一种:String,另一种:String[],此方法会自动判断调用哪个方法。
*
* @param value
* 需要处理的参数。
* @return 处理后的值。
*/
protected Object trim(Object value) {
if (value instanceof String[]) {
return trim((String[]) value);
}
return trim(value.toString());
}
/**
* 去除某个字符串的前后空格。
*
* @param value
* 需要处理的参数。
* @return 处理后的值。
*/
protected String trim(String value) {
if (value != null && value.length() > 0) {
return value.trim();
}
return value;
}
/**
* 去除某个数组中所有的值的前后空格。
*
* @param values
* 需要处理的数组。
* @return 处理后的值,当数组的length为1时,则返回一个String,反之返回一个数组。
*/
protected Object trim(String[] values) {
if (values != null && values.length > 0) {
int len = values.length;
for (int i = 0; i < len; i++) {
values[i] = trim(values[i]);
}
}
if (values.length == 1) {
return values[0];
}
return values;
}
/**
*
* @return 不处理的对象。
*/
public List<String> getExcludeNames() {
return excludeNames;
}
}
这个Filter实现原理非常简单,我会过滤所有的请求,HttpServletRequestWrapper2继承自HttpServletRequestWrapper,在构造函数中需要一个HttpServletRequest对象(这个request是web窗口创建的),然后我重载了上面所说的3个方法,在方法内部每次会去过滤当前值,这是利用了Java多态特性。在使用getParameterMap时较为麻烦,原理一样。
当然我们有时候可能有些特殊情况不需要过滤前后空格或者其它一些规则,这里我们可以使用exclude属性来判断是否过滤此属性。
DEMO:
<form action="test!create.action" method="post">
name:
<input name="name" value=" My name is haha.. " />
<br />
<!-- This is a String,isn't number. -->
age:
<input name="age" value=" 15 " />
<br />
email:
<input name="email" value=" grasszring@gmail.com " />
<br />
email2:
<input name="email" value=" grasszring@foxmail.com " />
<br />
<input type="submit" value=" submit " />
</form>
web.xml
<filter>
<filter-name>requestParameter</filter-name>
<filter-class>com.onlyeffort.commons.web.filter.RequestParameterFilter</filter-class>
<init-param>
<!-- 不需要过滤此参数 -->
<param-name>exclude</param-name>
<param-value>email</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>requestParameter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
action
@Action(params = { "actionName", "test" })
@Result(location = "http://www.google.com", type = "redirect")
@SuppressWarnings("serial")
public class TestController extends ActionSupport {
private String name;
private Integer age;
private String[] email;
//.. get set method.
@Override
public String create() throws CreateFailureException {
System.out.println(name);
System.out.println(age);
for (String mail : email) {
System.out.println(mail);
}
return SUCCESS;
}
}
分享到:
相关推荐
在`doFilter()`方法中,我们可以对`HttpServletRequest`的`getParameterMap()`方法返回的参数映射进行修改。这个映射包含了所有请求参数的键值对,其中键是参数名,值是一个字符串数组,因为同一个参数名可能对应多...
- 客户端重定向:当需要向客户端返回一个重定向响应时,可以利用这个方法获取原始请求的URL并进行修改。 - URL构建:用于构造新的URL进行页面跳转或API调用。 #### 三、路径获取示例代码 以下是在JSP页面中获取...
然而,需要注意的是,`HttpServletRequest`对象通常是只读的,直接修改`getParameterMap()`返回的`Map`不会改变实际请求中的参数。这是因为`HttpServletRequest`的内部结构并不直接暴露给开发者,而是通过API进行...
`HttpServletRequestWrapper` 是Servlet API中的一个抽象类,它是`HttpServletRequest` 的包装类,可以用来扩展或修改原始请求对象的功能。 标题“使用HttpServletRequestWrapper在filter修改request参数”揭示了...
对request请求进行拦截,对请求参数修改。常用于前台提交表单参数关键字的过滤。此工具可以对参数拦截并转义后提交到对应的处理类。 除了添加两个JsFilter.java和GetHttpServletRequestWrapper.java之外,需要在web....
通过这种方式,装饰模式使得在不修改HttpServletRequest本身的情况下,我们可以扩展其功能,解决了在Servlet过滤器中无法直接修改请求参数的问题。 总之,装饰模式在Servlet编程中提供了一种灵活的、非侵入式的扩展...
- `Wrapper`机制,允许在不修改核心实现的情况下添加自定义行为。 - 针对请求头、参数和cookies的存储结构。 - 对于POST请求,可能包含解析multipart/form-data和application/x-www-form-urlencoded内容的逻辑。 `...
继承HttpServletRequestWrapper实现类,重新相关方法,实现自定义增加请求参数,通常是由于需要对参数进行特殊业务处理,然而HttpServletRequest的request.getPrameterMap是不允许修改的(被锁,可查看底层源码),...
高级参数绑定是指在Controller方法中,Spring MVC能够自动将请求参数绑定到方法参数上,包括基本类型、复杂对象甚至自定义类型。例如,可以使用`@RequestParam`、`@PathVariable`、`@RequestHeader`、`@RequestBody`...
如果后期有新的需求,如增加请求参数的验证,我们可以再创建一个新的装饰器类,而无需修改已有的代码。 总结来说,"JavaWeb之装饰HttpServletRequest对象"涉及到的知识点包括: 1. **HttpServletRequest接口**:...
java通过HttpServletRequest获取post请求中的body内容的方法 java web应用中,获取post请求body中的内容是一个常见的需求。通常,我们可以使用request对象的getParameter()方法来获取url参数或ajax提交的参数。但是...
对项目中的所有参数去除前后空格...可以基于此过滤器实现过滤跨站脚本攻击,参数的增加,修改!敏感词汇过滤。实现原理为重写HttpServletRequestWrapper,获取参数的方法。include和 Forwarded 内部转发不在过滤之内。
HttpServletRequest对象包含了客户端请求的所有信息,包括请求URL、请求头、请求参数等。以下是一些常用方法: 1. **获取客户端信息**: - `getRequestURL()` 返回完整的请求URL。 - `getRequestURI()` 获取资源...
1. 获取请求参数:这可以通过HttpServletRequest对象的getParameter()或getParameterValues()方法实现,获取到用户提交的所有参数。 2. 检查参数值:遍历每个参数,检查其是否包含空格。 3. 去空处理:如果发现参数...
Zuul 中修改请求参数信息的方法 在 Spring Cloud 中, Zuul 是一个基于 JVM 的路由和服务端的负载均衡器,提供了认证、压力测试、金丝雀测试、动态路由、负载削减、安全、静态响应处理、主动/主动交换管理等功能。 ...
本文将深入探讨如何在JSP页面中获取Servlet请求中的参数,并将其传递到另一个JSP页面。 首先,我们需要配置`web.xml`文件,这是部署描述符,它定义了Servlet的映射和配置。以下是一个示例配置: ```xml ...
- 修改控制器方法`queryItem`,添加形参数组`ids`,用于接收前端传来的多个商品ID。 ##### 1.3 List参数类型 - **需求场景**:实现商品数据的批量修改功能。 - **实现方法**: - 在前端界面增加批量修改的功能...
在拦截器链中,每个拦截器都有机会修改ValueStack中的属性值,这意味着在Action方法执行前,请求参数可以在拦截器之间传递和修改。最终,当拦截器链执行完毕,ValueStack顶层的属性值会被赋给Action类的相应属性,...
2. POST方法:这种方式更为安全,因为参数不显示在URL中,适用于提交数据或修改操作。当用户点击“购买”按钮时,表单数据(如CD ID和数量)会被封装在HTTP请求的主体中,Servlet通过`request.getParameter()`方法...
我们可以修改控制器方法,添加HttpServletRequest作为参数: ```java @RequestMapping(value = "/demo", method = RequestMethod.POST) public String demo(HttpServletRequest request) throws IOException { // ...