注冊(cè)表單驗(yàn)證(轉(zhuǎn),如有侵權(quán)請(qǐng)聯(lián)絡(luò)我馬上刪除)

          文本框:
圖3.1  實(shí)例運(yùn)行效果網(wǎng)站在注冊(cè)新用戶過程中,需要驗(yàn)證很多內(nèi)容。例如,用戶名是否已存在,E-mail是否已被人使用,驗(yàn)證碼是否正確等。傳統(tǒng)方式是使用客戶端JavaScript做初步驗(yàn)證,用戶提交表單后在服務(wù)器端做進(jìn)一步驗(yàn)證。如果用戶輸入的內(nèi)容有錯(cuò)誤,會(huì)返回注冊(cè)頁(yè)面,提示用戶修改。使用了Ajax技術(shù)后,很多原來必須提交到服務(wù)器才能驗(yàn)證的內(nèi)容,可以在不刷新頁(yè)面的情況下直接驗(yàn)證。本例就演示了這個(gè)過程,實(shí)例運(yùn)行效果如圖3.1所示。

          3.1.1  技術(shù)要點(diǎn)

          本例中要驗(yàn)證的內(nèi)容有用戶名、密碼、E-mail和驗(yàn)證碼4部分內(nèi)容。但從技術(shù)實(shí)現(xiàn)上主要有3種形式,下面來一一介紹。

          1.驗(yàn)證用戶名和E-mail是否已存在

          在用戶輸入用戶名或E-mail之后,使用XMLHttpRequest對(duì)象將用戶輸入的信息發(fā)送給服務(wù)器。服務(wù)器判斷是否存在同名用戶或E-mail地址。驗(yàn)證完畢后將信息反饋給客戶端,由客戶端顯示驗(yàn)證結(jié)果。這樣用戶在未提交整個(gè)表單前,就可以知道輸入的用戶名或E-mail是否可以使用。

          2.密碼驗(yàn)證

          密碼驗(yàn)證比較簡(jiǎn)單,不需要到服務(wù)器判斷。只需在客戶端對(duì)兩次輸入的密碼進(jìn)行比對(duì),當(dāng)輸入一致時(shí)通過驗(yàn)證,否則提示用戶密碼有誤。

          3.生成驗(yàn)證碼與校驗(yàn)過程

          驗(yàn)證碼主要是防止惡意用戶使用工具自動(dòng)進(jìn)行批量注冊(cè),搶占用戶名。其基本原理是在服務(wù)器生成一個(gè)隨機(jī)數(shù)字,并放入用戶session中??蛻舳孙@示使用該隨機(jī)數(shù)字生成的圖片,用戶按照?qǐng)D片內(nèi)容輸入驗(yàn)證碼。最后將用戶的輸入與session中的驗(yàn)證碼進(jìn)行比對(duì),如果一致則驗(yàn)證成功。本例中使用Java類庫(kù)中圖像API生成包含三位數(shù)字驗(yàn)證碼的PNG格式圖片。具體的代碼可參考code.jsp。

          4.將驗(yàn)證函數(shù)封裝在Checker對(duì)象中

          以上3種方式的驗(yàn)證函數(shù)都封裝在一個(gè)Checker對(duì)象中。里面包含的checkNode函數(shù)對(duì)應(yīng)用戶名和E-mail驗(yàn)證,以及驗(yàn)證碼校驗(yàn)。checkPassword函數(shù)對(duì)應(yīng)密碼驗(yàn)證。所有的驗(yàn)證結(jié)果第一個(gè)字符是數(shù)字0或1,分別表示驗(yàn)證失敗或成功。后面緊跟驗(yàn)證結(jié)果的詳細(xì)文字說明。showInfo函數(shù)根據(jù)驗(yàn)證結(jié)果進(jìn)行不同樣式的顯示。

          3.1.2  數(shù)據(jù)庫(kù)設(shè)計(jì)

          本實(shí)例使用名為users的數(shù)據(jù)庫(kù)表,包含的數(shù)據(jù)如圖3.2所示。具體的創(chuàng)建數(shù)據(jù)表語句如下:

          CREATE TABLE 'users' (

            'id' int(11) NOT NULL auto_increment,

            'username' varchar(255) NOT NULL,

            'password' varchar(255) NOT NULL,

            'E-mail' varchar(255) NOT NULL,

            PRIMARY KEY  ('id')

          )

          圖3.2  表users包含的數(shù)據(jù)

          本實(shí)例共包括4個(gè)文件:用戶操作界面register.html,服務(wù)器端響應(yīng)文件checker.jsp,驗(yàn)證碼圖片生成文件code.jsp,以及JavaScript文件checker.js。

          3.1.3  用戶操作界面register.html

          頁(yè)面包含操作界面樣式以及注冊(cè)表單。表單中各元素通過onblur(失去焦點(diǎn))事件觸發(fā)驗(yàn)證函數(shù)。每個(gè)表單元素對(duì)應(yīng)一個(gè)div,用于顯示驗(yàn)證結(jié)果。

          <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

          <html>

          <head>

          <meta http-equiv="Content-type" content="text/html; charset=utf-8">

          <title>注冊(cè)表單驗(yàn)證</title>

          <style type="text/css">

          /* 頁(yè)面字體樣式 */

          body, td, input {

              font-family:Arial;

              font-size:12px;

          }

          /* 表格基本樣式 */

          table.default {

              border-collapse:collapse;

              width:300px;

          }

          /* 表格單元格樣式 */

          table.default td {

              border:1px solid black;

              padding:3px;

          }

          /* 列頭樣式 */

          table.default td.item {

              background:#006699;

              color:#fff;

          }

          /* 正常信息樣式 */

          div.ok {

              color:#006600;

          }

          /* 警告信息樣式 */

          div.warning {

              color:#FF0000;

          }

          </style>

          <!-- 引入外部checker.js文件 -->

          <script type="text/javascript" src="checker.js"></script>

          </head>

          <body>

          <h1>注冊(cè)表單驗(yàn)證</h1>

          <form method="post" action="register.jsp"

                 onsubmit="alert('后面的注冊(cè)過程與傳統(tǒng)方式相同。');return false">

          <table class="default">

          <tr>

              <td class="item" width="30%">用戶名:</td>

              <td width="70%">

                  <input type="text" name="username" id="username" onblur="Checker.checkNode(this)">

                  <div id="usernameCheckDiv" class="warning">請(qǐng)輸入用戶名。</div>

              </td>

          </tr>

          <tr>

              <td class="item">密碼:</td>

              <td>

                  <input type="password" name="password" id="password" onblur="Checker.checkPassword()">

                  <div id="passwordCheckDiv" class="warning">請(qǐng)輸入密碼。</div>

              </td>

          </tr>

          <tr>

              <td class="item">密碼驗(yàn)證:</td>

              <td>

                  <input type="password" name="password2" id="password2" onblur="Checker.checkPassword()">

                  <div id="password2CheckDiv" class="warning">請(qǐng)?jiān)俅屋斎朊艽a。</div>

              </td>

          </tr>

          <tr>

              <td class="item">E-mail:</td>

              <td>

                  <input type="text" name="E-mail" id="E-mail" onblur="Checker.checkNode(this)">

                  <div id="E-mailCheckDiv" class="warning">請(qǐng)輸入郵件地址。</div>

              </td>

          </tr>

          <tr>

              <td class="item">驗(yàn)證碼:</td>

              <td>

                  <input type="text" name="code" id="code" size="5"

                          onblur="Checker.checkNode(this)">

                  <img src="code.jsp" width="40" height="20" border="0" alt="">

                  <div id="codeCheckDiv" class="warning">請(qǐng)輸入圖片中的數(shù)字驗(yàn)證碼。</div>

              </td>

          </tr>

          <tr>

              <td colspan="2" align="center">

                  <input type="submit" value="注冊(cè)">

              </td>

          </tr>

          </table>

          </form>

          </body>

          </html>

          3.1.4  服務(wù)器端響應(yīng)文件checker.jsp

          服務(wù)器端響應(yīng)文件主要包含兩類驗(yàn)證,根據(jù)用戶提交的表單元素名確定驗(yàn)證方式。如果表單元素名是userName或E-mail,則進(jìn)行數(shù)據(jù)查詢,判斷是否存在相同信息。如果是code,則直接通過對(duì)比session中的驗(yàn)證碼進(jìn)行判斷。

          <%@ page contentType="text/plain; charset=UTF-8"%>

          <%@ page language="java"%>

          <%@ page import="java.sql.*,ajax.db.DBUtils"%>

          <%!

              //查詢數(shù)據(jù)庫(kù)是否存在相同信息

              boolean hasSameValue(String name, String value) {

                  boolean result = false;                                                                 //保存檢測(cè)結(jié)果

                  //定義查詢數(shù)據(jù)庫(kù)的SQL語句

                  String sql = "select * from users where " + name + " = ?";

                  Connection conn = null;                                                     //聲明Connection對(duì)象

                  PreparedStatement pstmt = null;                                               //聲明PreparedStatement對(duì)象

                  ResultSet rs = null;                                                              //聲明ResultSet對(duì)象

                  try {

                      conn = DBUtils.getConnection();                              //獲取數(shù)據(jù)庫(kù)連接

                      pstmt = conn.prepareStatement(sql);                      //根據(jù)sql創(chuàng)建PreparedStatement

                      pstmt.setString(1, value);                                           //設(shè)置參數(shù)

                      rs = pstmt.executeQuery();                                        //執(zhí)行查詢,返回結(jié)果集

                      //根據(jù)結(jié)果集是否存在決定查詢結(jié)果

                      if (rs.next()) {

                          result = true;

                      } else {

                          result = false;

                      }

                  } catch (SQLException e) {

                      System.out.println(e.toString());

                  } finally {

                      DBUtils.close(rs);                                                         //關(guān)閉結(jié)果集

                      DBUtils.close(pstmt);                                                  //關(guān)閉PreparedStatement

                      DBUtils.close(conn);                                                   //關(guān)閉連接

                  }

                  return result;

              }

          %>

          <%

              out.clear();                                                                                     //清空當(dāng)前的輸出內(nèi)容(空格和換行符)

              request.setCharacterEncoding("UTF-8");                               //設(shè)置請(qǐng)求體字符編碼格式為UTF-8

              String name = request.getParameter("name");                     //獲取name參數(shù)

              String value = request.getParameter("value");                      //獲取value參數(shù)

              String info = null;                                                                         //用于保存提示對(duì)象的名稱

              //如果需要判斷的是驗(yàn)證碼,采用session方式驗(yàn)證

              if ("code".equals(name)) {

                  //獲取session中保存的驗(yàn)證碼

                  String sessionCode = (String) session.getAttribute("_CODE_");

                  //根據(jù)對(duì)比結(jié)果輸出響應(yīng)信息

                  if (value != null && value.equals(sessionCode)) {

                      out.print("1驗(yàn)證碼正確。");

                  } else {

                      out.print("0驗(yàn)證碼錯(cuò)誤。");

                  }

              } else {

                  //根據(jù)name變量確定提示對(duì)象的名稱

                  if ("username".equals(name)) {

                      info = "用戶名";

                  } else if ("E-mail".equals(name)) {

                      info = "郵件地址";

                  }

                  //根據(jù)是否存在相同信息輸出對(duì)應(yīng)的響應(yīng)

                  if (hasSameValue(name, value)) {

                      out.print("0該" + info + "已存在,請(qǐng)更換" + info + "。");

                  } else {

                      out.print("1該" + info + "可正常使用。");

                  }

              }

          %>

          3.1.5  驗(yàn)證碼生成文件code.jsp

          生成驗(yàn)證碼要注意頁(yè)首contentType的設(shè)置為image/png。主要使用了awt組件和imageio組件中相關(guān)的API進(jìn)行圖片生成,隨機(jī)數(shù)是使用java.util.Random類生成的。詳細(xì)的過程參考以下代碼:

          <%@ page contentType="image/png" import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*" %><%

          //設(shè)置頁(yè)面不緩存

          response.setHeader("Pragma","No-cache");

          response.setHeader("Cache-Control","no-cache");

          response.setDateHeader("Expires", 0);

          int width=40;                                                                                         //設(shè)置圖片寬度

          int height=20;                                                                                        //設(shè)置圖片高度

          //創(chuàng)建緩存圖像

          BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

          Graphics g = image.getGraphics();                                                  //獲取圖形

          g.setColor(new Color(000, 102, 153));                                           //設(shè)置背景色

          g.fillRect(0, 0, width, height);                                                             //填充背景

          g.setColor(new Color(000, 000, 000));                                           //設(shè)置邊框顏色

          g.drawRect(0, 0, width-1, height-1);                                                 //繪制邊框

          g.setFont(new Font("Arial", Font.PLAIN, 16));                                //設(shè)定字體

          Random random = new Random();                                                 //生成隨機(jī)類

          //隨機(jī)產(chǎn)生3位數(shù)字驗(yàn)證碼

          StringBuffer sbRan = new StringBuffer();                                       //保存驗(yàn)證碼文本

          for (int i=0; i<3; i++){

              String ranNum = String.valueOf(random.nextInt(10));

              sbRan.append(ranNum);

              //將驗(yàn)證碼繪制到圖像中

              g.setColor(new Color(255, 255, 255));

              g.drawString(ranNum, 10 * i + 5, 16);

          }

          g.dispose();                                                                                           //部署圖像

          session.setAttribute("_CODE_", sbRan.toString());                       //將驗(yàn)證碼保存在session對(duì)象中供對(duì)比

          ImageIO.write(image, "PNG", response.getOutputStream());              //輸出圖像到頁(yè)面

          %>

          3.1.6  JavaScript文件checker.js

          所有的驗(yàn)證函數(shù)都封裝在一個(gè)名為Checker的對(duì)象中,獨(dú)立存在于checker.js文件里。函數(shù)調(diào)用流程如圖3.3所示。

          圖3.3  函數(shù)調(diào)用流程

          var Checker = new function() {

              this._url = "checker.jsp";                                                                      //服務(wù)器端文件地址

              this._infoDivSuffix = "CheckDiv";                                                      //提示信息div的統(tǒng)一后綴

              //檢查普通輸入信息

              this.checkNode = function(_node) {

                  var nodeId = _node.id;                                                                          //獲取節(jié)點(diǎn)id

                  if (_node.value!="") {

                      var xmlHttp=this.createXmlHttp();                                               //創(chuàng)建XmlHttpRequest對(duì)象

                      xmlHttp.onreadystatechange = function() {

                          if (xmlHttp.readyState == 4) {

                              //調(diào)用showInfo方法顯示服務(wù)器反饋信息

                              Checker.showInfo(nodeId + Checker._infoDivSuffix,

                                                  xmlHttp.responseText);

                          }

                      }

                      xmlHttp.open("POST", this._url, true);

                      xmlHttp.setRequestHeader(

                                               "Content-type","application/x-www-form-urlencoded");

                      xmlHttp.send("name=" + encodeURIComponent(_node.id) +

                                   //發(fā)送包含用戶輸入信息的請(qǐng)求體

                                   "&value=" + encodeURIComponent(_node.value));

                  }

              }

              //顯示服務(wù)器反饋信息

              this.showInfo = function(_infoDivId, text) {

                  var infoDiv = document.getElementById(_infoDivId); //獲取顯示信息的div

                  var status = text.substr(0,1);                                               //反饋信息的第一個(gè)字符表示信息類型

                  if (status == "1") {

                      infoDiv.className = "ok";                                         //檢查結(jié)果正常

                  } else {

                      infoDiv.className = "warning";                               //檢查結(jié)果需要用戶修改

                  }

                  infoDiv.innerHTML = text.substr(1);                                 //寫回詳細(xì)信息

              }

              //用于創(chuàng)建XMLHttpRequest對(duì)象

              this.createXmlHttp = function() {

                  var xmlHttp = null;

                  //根據(jù)window.XMLHttpRequest對(duì)象是否存在使用不同的創(chuàng)建方式

                  if (window.XMLHttpRequest) {

                     xmlHttp = new XMLHttpRequest();                             //FireFox、Opera等瀏覽器支持的創(chuàng)建方式

                  } else {

                     xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");//IE瀏覽器支持的創(chuàng)建方式

                  }

                  return xmlHttp;

              }

              //檢查兩次輸入的密碼是否一致

              this.checkPassword = function() {

                  var p1 = document.getElementById("password").value;                //獲取密碼

                  var p2 = document.getElementById("password2").value;             //獲取驗(yàn)證密碼

                  //當(dāng)兩部分密碼都輸入完畢后進(jìn)行判斷

                  if (p1 != "" && p2 != "") {

                      if (p1 != p2) {

                          this.showInfo("password2" + Checker._infoDivSuffix,

                                           "0密碼驗(yàn)證與密碼不一致。");

                      } else {

                          this.showInfo("password2" + Checker._infoDivSuffix, "1");

                      }

                  } else if (p1 != null) {

                      this.showInfo("password" + Checker._infoDivSuffix, "1");

                  }

              }

          }

          3.1.7  小結(jié)

          表單驗(yàn)證在網(wǎng)站中是很常見的內(nèi)容,可以說只要是用到表單的地方,十有八九需要進(jìn)行內(nèi)容驗(yàn)證。當(dāng)遇到需要提交給服務(wù)器才能驗(yàn)證的字段時(shí),使用Ajax技術(shù)是一個(gè)非常好的選擇。本例雖然只講解了用戶注冊(cè)的表單驗(yàn)證,但其基本思想和實(shí)現(xiàn)技術(shù)可以推廣到各種類型的表單驗(yàn)證中去。

          posted on 2009-04-20 12:55 MichaelLee 閱讀(2045) 評(píng)論(2)  編輯  收藏 所屬分類: JavaScript

          評(píng)論

          # re: 注冊(cè)表單驗(yàn)證(轉(zhuǎn),如有侵權(quán)請(qǐng)聯(lián)絡(luò)我馬上刪除) 2010-08-21 16:53 sdfas

          asdfasdfasdf  回復(fù)  更多評(píng)論   

          # re: 注冊(cè)表單驗(yàn)證(轉(zhuǎn),如有侵權(quán)請(qǐng)聯(lián)絡(luò)我馬上刪除) 2010-08-21 16:53 sdfas

          sdfasdfa  回復(fù)  更多評(píng)論   

          <2009年4月>
          2930311234
          567891011
          12131415161718
          19202122232425
          262728293012
          3456789

          導(dǎo)航

          統(tǒng)計(jì)

          公告

          ====Michael Lee====
          =Java Sofware Engineer=
          =Work @ Beijing=
          ---再煩,也別忘微笑;再急,也要注意語氣;再苦,也別忘堅(jiān)持;再累,也要愛自己!---
          ---低調(diào)做人,你會(huì)一次比一次穩(wěn)??;高調(diào)做事,你會(huì)一次比一次優(yōu)秀---
          ---成功的時(shí)候不要忘記過去;失敗的時(shí)候不要忘記還有未來---

          常用鏈接

          留言簿(2)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 遂昌县| 介休市| 兴宁市| 上杭县| 云霄县| 崇阳县| 萨嘎县| 汽车| 廊坊市| 桦川县| 沂水县| 通山县| 新干县| 和林格尔县| 云南省| 大余县| 塔城市| 赫章县| 虹口区| 乐亭县| 黄梅县| 渭南市| 宁国市| 玉林市| 伽师县| 泊头市| 上林县| 定日县| 军事| 武邑县| 昌图县| 双城市| 乐安县| 平度市| 孙吴县| 铜陵市| 吕梁市| 大埔区| 南部县| 宝丰县| 稷山县|