J2EE数据验证的一些开发建议
说在前面:非原创。
输入数据验证:虽然为了用户的方便,可以提供“客户端”层数据的数据验证,但必须使用servlet 在服务器层执行验证。 客户端验证本身就不安全,因为这些验证可轻易绕过,例如,通过禁用 javascript。一份好的设计通常需要 web 应用程序框架,以提供服务器端实用程序例程,从而验证以下内容:
[1] 必需字段;[2] 字段数据类型(缺省情况下,所有 http 请求参数都是“字符串”);[3] 字段长度;[4] 字段范围;[5] 字段选项;[6] 字段模式;[7] cookie 值;[8] http 响应。
好的做法是将以上例程作为“验证器”实用程序类中的静态方法实现。以下部分描述验证器类的一个示例。
[1] 必需字段
// java example to validate required fields public class validator { ... public static boolean validaterequired(string value) { boolean isfieldvalid = false; if (value != null && value.trim().length() > 0) { isfieldvalid = true; } return isfieldvalid; } ... } ... string fieldvalue = request.getparameter("fieldname"); if (validator.validaterequired(f ieldvalue)) { // fieldvalue is valid, continue processing request ... } // java example to validate that a f ield is an int number public class validator { ... public static boolean validateint(string value) { boolean isfieldvalid = false; try { integer.parseint(value); isfieldvalid = true; } catch (exception e) { isfieldvalid = false; } return isfieldvalid; } ... } ... // check if the http request parameter is of type int string f ieldvalue = request.getparameter("f ieldname"); if (validator.validateint(f ieldvalue)) { // f ieldvalue is valid, continue processing request ... } // example to convert the http request parameter to a primitive wrapper data type // and store this value in a request attribute for further processing string f ieldvalue = request.getparameter("f ieldname"); if (validator.validateint(f ieldvalue)) { // convert f ieldvalue to an integer integer integervalue = integer.getinteger(f ieldvalue); // store integervalue in a request attribute request.setattribute("f ieldname", integervalue); } ... / / use the request attribute for further processing integer integervalue = (integer)request.getattribute("f ieldname"); ... // example to validate the f ield length public class validator { ... public static boolean validatelength(string value, int minlength, int maxlength) { string validatedvalue = value; if (!validaterequired(value)) { validatedvalue = ""; } return (validatedvalue.length() >= minlength && validatedvalue.length() <= maxlength); } ... } ... string username = request.getparameter("username"); if (validator.validaterequired(username)) { if (validator.validatelength(username, 8, 20)) { / / username is valid, continue further processing ... } } / / example to validate the f ield range public class validator { ... public static boolean validaterange(int value, int min, int max) { return (value >= min && value <= max); } ... } ... string f ieldvalue = request.getparameter("numberofchoices");if (validator.validaterequired(f ieldvalue)) { if (validator.validateint(f ieldvalue)) { int numberofchoices = integer.parseint(f ieldvalue); if (validator.validaterange(numberofchoices, 10, 20)) { // numberofchoices is valid, continue processing request ... } } } // example to validate user selection against a list of options public class validator { ... public static boolean validateoption(object[] options, object value) { boolean isvalidvalue = false; try { list list = arrays.aslist(options); if (list != null) { isvalidvalue = list.contains(value); } } catch (exception e) { } return isvalidvalue; } ... } ... // allowed options string[] options = {"option1", "option2", "option3"); // verify that the user selection is one of the allowed options string userselection = request.getparameter("userselection"); if (validator.validateoption(options, userselection)) { // valid user selection, continue processing request ... } // example to validate that a given value matches a specif ied pattern // using the java 1.4 regular expression package import java.util.regex.pattern; import java.util.regexe.matcher; public class validator { ... public static boolean matchpattern(string value, string expression) { boolean match = false; if (validaterequired(expression)) { match = pattern.matches(expression, value); } return match; } ... } ... // verify that the username request parameter is alphanumeric string username = request.getparameter("username"); if (validator.matchpattern(username, "^[a-za-z0-9]*$")) { / / username is valid, continue processing request ... } // example to validate a required cookie value // first retrieve all available cookies submitted in the http request cookie[] cookies = request.getcookies(); if (cookies != null) { // f ind the "user" cookie for (int i=0; i<cookies.length; ++i) { if (cookies[i].getname().equals("user")) { / / validate the cookie value if (validator.validaterequired(cookies[i].getvalue()) { // valid cookie value, continue processing request ... } } } } // example to f ilter sensitive data to prevent cross-site scripting public class validator { ... public static string f ilter(string value) { if (value == null) { return null; } stringbuf fer result = new stringbuf fer(value.length()); for (int i=0; i<value.length(); ++i) { switch (value.charat(i)) { case '<': result.append("&lt;"); break; case '>': result.append("&gt;"); break; case '"': result.append("&quot;"); break; case '\'': result.append("&#39;"); break; case '%': result.append("&#37;"); break; case ';': result.append("&#59;"); break; case '(': result.append("&#40;"); break; case ')': result.append("&#41;"); break; case '&': result.append("&amp;"); break; case '+': result.append("&#43;"); break; default: result.append(value.charat(i)); break; } return result; } ... } ... // filter the http response using validator.filter printwriter out = response.getwriter(); // set output response out.write(validator.filter(response)); out.close(); // example to f ilter all sensitive characters in the http response using a java filter. // this example is for illustration purposes since it will f ilter all content in the response, including html tags! public class sensitivecharsfilter implements filter { ... public void dofilter(servletrequest request, servletresponse response, filterchain chain) throws ioexception, servletexception { printwriter out = response.getwriter(); responsewrapper wrapper = new responsewrapper((httpservletresponse)response); chain.dofilter(request, wrapper); chararraywriter caw = new chararraywriter(); caw.write(validator.f ilter(wrapper.tostring())); response.setcontenttype("text/html"); response.setcontentlength(caw.tostring().length()); out.write(caw.tostring()); out.close(); } ... public class charresponsewrapper extends httpservletresponsewrapper { private chararraywriter output; public string tostring() { return output.tostring(); } public charresponsewrapper(httpservletresponse response){ super(response); output = new chararraywriter(); } public printwriter getwriter(){ return new printwriter(output); } } } // example to secure a cookie, i.e. instruct the browser to / / send the cookie using a secure protocol cookie cookie = new cookie("user", "sensitive"); cookie.setsecure(true); response.addcookie(cookie);