J2EE數據驗證的一些開發建議 – JAVA編程語言程序開發技術文章

說在前面:非原創。

輸入數據驗證:雖然為瞭用戶的方便,可以提供“客戶端”層數據的數據驗證,但必須使用servlet 在服務器層執行驗證。 客戶端驗證本身就不安全,因為這些驗證可輕易繞過,例如,通過禁用 javascript。一份好的設計通常需要 web 應用程序框架,以提供服務器端實用程序例程,從而驗證以下內容:
[1] 必需字段;
[2] 字段數據類型(缺省情況下,所有 http 請求參數都是“字符串”);
[3] 字段長度;
[4] 字段范圍;
[5] 字段選項;
[6] 字段模式;
[7] cookie 值;
[8] http 響應。

好的做法是將以上例程作為“驗證器”實用程序類中的靜態方法實現。以下部分描述驗證器類的一個示例。
[1] 必需字段
Java代碼 
// 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      …  } 

[2] 輸入的 web 應用程序中的字段數據類型和輸入參數欠佳。例如,所有 http 請求參數或cookie值的類型都是“字符串”。開發者負責驗證輸入的數據類型是否正確。 使用java基本包裝程序類,來檢查是否可將字段值安全地轉換為所需的基本數據類型。
驗證數字字段(int 類型)的方式的示例:
Java代碼 
// 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      …  } 

好的做法是將所有http請求參數轉換為其各自的數據類型。例如,開發者應將請求參數的“integervalue”存儲在請求屬性中,並按以下示例所示來使用:
Java代碼 
// 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");  … 

應用程序應處理的主要 java 數據類型:
byte
short
integer
long
float
double
date

[3] 字段長度“始終”確保輸入參數(http請求參數或cookie值)有最小長度和/或最大長度的限制。
以下示例驗證 username 字段的長度是否在 8 至 20 個字符之間:
Java代碼 
// 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 &amp;&amp;                      validatedvalue.length() <= maxlength);      }      …  }  …  string username = request.getparameter("username");  if (validator.validaterequired(username)) {      if (validator.validatelength(username, 8, 20)) {          / / username is valid, continue further processing          …      }  } 

[4] 字段范圍
始終確保輸入參數是在由功能需求定義的范圍內。
以下示例驗證輸入 numberofchoices 是否在 10 至 20 之間:
Java代碼 
/ / example to validate the f ield range  public class validator {      …      public static boolean validaterange(int value, int min, int max) {          return (value >= min &amp;&amp; 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              …          }      }  } 

[5] 字段選項 web 應用程序通常會為用戶顯示一組可供選擇的選項(例如,使用select html 標記),但不能執行服務器端驗證以確保選定的值是其中一個允許的選項。請記住,惡意用戶能夠輕易修改任何選項值。始終針對由功能需求定義的受允許的選項來驗證選定的用戶值。
以下示例驗證用戶針對允許的選項列表進行的選擇:
Java代碼 
// 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      …  } 

[6] 字段模式
始終檢查用戶輸入與由功能需求定義的模式是否匹配。例如,如果 username 字段應僅允許字母數字字符,且不區分大小寫,那麼請使用以下正則表達式:^[a-za-z0-9]*$。
執行正則表達式驗證的示例:
Java代碼 
// 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      …  } 

[7]cookie值使用javax.servlet.http.cookie對象來驗證cookie值。適用於cookie值的相同的驗證規則(如上所述)取決於應用程序需求(如驗證必需值、驗證長度等)。
驗證必需 cookie 值的示例:
Java代碼 
// 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                  …              }          }          }  } 

[8] http 響應
[8-1] 過濾用戶輸入要保護應用程序免遭跨站點腳本編制的攻擊,請通過將敏感字符轉換為其對應的字符實體來清理 html。這些是 html 敏感字符:< > " ' % ; ) ( &amp; +。
以下示例通過將敏感字符轉換為其對應的字符實體,來過濾指定字符串:
Java代碼 
// 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("&amp;lt;");                  break;              case '>':                  result.append("&amp;gt;");                  break;              case '"':                  result.append("&amp;quot;");                  break;              case '\'':                  result.append("&amp;#39;");                  break;              case '%':                  result.append("&amp;#37;");                  break;              case ';':                  result.append("&amp;#59;");                  break;              case '(':                  result.append("&amp;#40;");                  break;              case ')':                  result.append("&amp;#41;");                  break;              case '&amp;':                  result.append("&amp;amp;");                  break;              case '+':                  result.append("&amp;#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(); 

java servlet api 2.3 引進瞭過濾器,它支持攔截和轉換 http 請求或響應。
以下示例使用 validator.f ilter 來用“servlet 過濾器”清理響應:
Java代碼 
// 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);          }      }  } 

[8-2] 保護cookie
在cookie中存儲敏感數據時,確保使用cookie.setsecure(佈爾標志)在 http 響應中設置cookie 的安全標志,以指導瀏覽器使用安全協議(如 https 或 ssl)發送cookie。
保護“用戶”cookie 的示例:
Java代碼 
// 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); 


全文結束,有問題的可以留言大傢探討。

作者“技術總結”
 

發佈留言