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("<"); break; case '>': result.append(">"); break; case '"': result.append("""); break; case '\'': result.append("'"); break; case '%': result.append("%"); break; case ';': result.append(";"); break; case '(': result.append("("); break; case ')': result.append(")"); break; case '&': result.append("&"); break; case '+': result.append("+"); 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);