注册表单验证(转,如有侵权请联络我马上删除)

文本框:
图3.1  实例运行效果网站在注册新用户过程中,需要验证很多内容。例如,用户名是否已存在,E-mail是否已被人使用,验证码是否正确等。传统方式是使用客户端JavaScript做初步验证,用户提交表单后在服务器端做进一步验证。如果用户输入的内容有错误,会返回注册页面,提示用户修改。使用了Ajax技术后,很多原来必须提交到服务器才能验证的内容,可以在不刷新页面的情况下直接验证。本例就演示了这个过程,实例运行效果如图3.1所示。

3.1.1  技术要点

本例中要验证的内容有用户名、密码、E-mail和验证码4部分内容。但从技术实现上主要有3种形式,下面来一一介绍。

1.验证用户名和E-mail是否已存在

在用户输入用户名或E-mail之后,使用XMLHttpRequest对象将用户输入的信息发送给服务器。服务器判断是否存在同名用户或E-mail地址。验证完毕后将信息反馈给客户端,由客户端显示验证结果。这样用户在未提交整个表单前,就可以知道输入的用户名或E-mail是否可以使用。

2.密码验证

密码验证比较简单,不需要到服务器判断。只需在客户端对两次输入的密码进行比对,当输入一致时通过验证,否则提示用户密码有误。

3.生成验证码与校验过程

验证码主要是防止恶意用户使用工具自动进行批量注册,抢占用户名。其基本原理是在服务器生成一个随机数字,并放入用户session中。客户端显示使用该随机数字生成的图片,用户按照图片内容输入验证码。最后将用户的输入与session中的验证码进行比对,如果一致则验证成功。本例中使用Java类库中图像API生成包含三位数字验证码的PNG格式图片。具体的代码可参考code.jsp。

4.将验证函数封装在Checker对象中

以上3种方式的验证函数都封装在一个Checker对象中。里面包含的checkNode函数对应用户名和E-mail验证,以及验证码校验。checkPassword函数对应密码验证。所有的验证结果第一个字符是数字0或1,分别表示验证失败或成功。后面紧跟验证结果的详细文字说明。showInfo函数根据验证结果进行不同样式的显示。

3.1.2  数据库设计

本实例使用名为users的数据库表,包含的数据如图3.2所示。具体的创建数据表语句如下:

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包含的数据

本实例共包括4个文件:用户操作界面register.html,服务器端响应文件checker.jsp,验证码图片生成文件code.jsp,以及JavaScript文件checker.js。

3.1.3  用户操作界面register.html

页面包含操作界面样式以及注册表单。表单中各元素通过onblur(失去焦点)事件触发验证函数。每个表单元素对应一个div,用于显示验证结果。

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

<html>

<head>

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

<title>注册表单验证</title>

<style type="text/css">

/* 页面字体样式 */

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>注册表单验证</h1>

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

       onsubmit="alert('后面的注册过程与传统方式相同。');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">请输入用户名。</div>

    </td>

</tr>

<tr>

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

    <td>

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

        <div id="passwordCheckDiv" class="warning">请输入密码。</div>

    </td>

</tr>

<tr>

    <td class="item">密码验证:</td>

    <td>

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

        <div id="password2CheckDiv" class="warning">请再次输入密码。</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">请输入邮件地址。</div>

    </td>

</tr>

<tr>

    <td class="item">验证码:</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">请输入图片中的数字验证码。</div>

    </td>

</tr>

<tr>

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

        <input type="submit" value="注册">

    </td>

</tr>

</table>

</form>

</body>

</html>

3.1.4  服务器端响应文件checker.jsp

服务器端响应文件主要包含两类验证,根据用户提交的表单元素名确定验证方式。如果表单元素名是userName或E-mail,则进行数据查询,判断是否存在相同信息。如果是code,则直接通过对比session中的验证码进行判断。

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

<%@ page language="java"%>

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

<%!

    //查询数据库是否存在相同信息

    boolean hasSameValue(String name, String value) {

        boolean result = false;                                                                 //保存检测结果

        //定义查询数据库的SQL语句

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

        Connection conn = null;                                                     //声明Connection对象

        PreparedStatement pstmt = null;                                               //声明PreparedStatement对象

        ResultSet rs = null;                                                              //声明ResultSet对象

        try {

            conn = DBUtils.getConnection();                              //获取数据库连接

            pstmt = conn.prepareStatement(sql);                      //根据sql创建PreparedStatement

            pstmt.setString(1, value);                                           //设置参数

            rs = pstmt.executeQuery();                                        //执行查询,返回结果集

            //根据结果集是否存在决定查询结果

            if (rs.next()) {

                result = true;

            } else {

                result = false;

            }

        } catch (SQLException e) {

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

        } finally {

            DBUtils.close(rs);                                                         //关闭结果集

            DBUtils.close(pstmt);                                                  //关闭PreparedStatement

            DBUtils.close(conn);                                                   //关闭连接

        }

        return result;

    }

%>

<%

    out.clear();                                                                                     //清空当前的输出内容(空格和换行符)

    request.setCharacterEncoding("UTF-8");                               //设置请求体字符编码格式为UTF-8

    String name = request.getParameter("name");                     //获取name参数

    String value = request.getParameter("value");                      //获取value参数

    String info = null;                                                                         //用于保存提示对象的名称

    //如果需要判断的是验证码,采用session方式验证

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

        //获取session中保存的验证码

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

        //根据对比结果输出响应信息

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

            out.print("1验证码正确。");

        } else {

            out.print("0验证码错误。");

        }

    } else {

        //根据name变量确定提示对象的名称

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

            info = "用户名";

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

            info = "邮件地址";

        }

        //根据是否存在相同信息输出对应的响应

        if (hasSameValue(name, value)) {

            out.print("0该" + info + "已存在,请更换" + info + "。");

        } else {

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

        }

    }

%>

3.1.5  验证码生成文件code.jsp

生成验证码要注意页首contentType的设置为image/png。主要使用了awt组件和imageio组件中相关的API进行图片生成,随机数是使用java.util.Random类生成的。详细的过程参考以下代码:

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

//设置页面不缓存

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

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

response.setDateHeader("Expires", 0);

int width=40;                                                                                         //设置图片宽度

int height=20;                                                                                        //设置图片高度

//创建缓存图像

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

Graphics g = image.getGraphics();                                                  //获取图形

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

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

g.setColor(new Color(000, 000, 000));                                           //设置边框颜色

g.drawRect(0, 0, width-1, height-1);                                                 //绘制边框

g.setFont(new Font("Arial", Font.PLAIN, 16));                                //设定字体

Random random = new Random();                                                 //生成随机类

//随机产生3位数字验证码

StringBuffer sbRan = new StringBuffer();                                       //保存验证码文本

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

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

    sbRan.append(ranNum);

    //将验证码绘制到图像中

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

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

}

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

session.setAttribute("_CODE_", sbRan.toString());                       //将验证码保存在session对象中供对比

ImageIO.write(image, "PNG", response.getOutputStream());              //输出图像到页面

%>

3.1.6  JavaScript文件checker.js

所有的验证函数都封装在一个名为Checker的对象中,独立存在于checker.js文件里。函数调用流程如图3.3所示。

图3.3  函数调用流程

var Checker = new function() {

    this._url = "checker.jsp";                                                                      //服务器端文件地址

    this._infoDivSuffix = "CheckDiv";                                                      //提示信息div的统一后缀

    //检查普通输入信息

    this.checkNode = function(_node) {

        var nodeId = _node.id;                                                                          //获取节点id

        if (_node.value!="") {

            var xmlHttp=this.createXmlHttp();                                               //创建XmlHttpRequest对象

            xmlHttp.onreadystatechange = function() {

                if (xmlHttp.readyState == 4) {

                    //调用showInfo方法显示服务器反馈信息

                    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) +

                         //发送包含用户输入信息的请求体

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

        }

    }

    //显示服务器反馈信息

    this.showInfo = function(_infoDivId, text) {

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

        var status = text.substr(0,1);                                               //反馈信息的第一个字符表示信息类型

        if (status == "1") {

            infoDiv.className = "ok";                                         //检查结果正常

        } else {

            infoDiv.className = "warning";                               //检查结果需要用户修改

        }

        infoDiv.innerHTML = text.substr(1);                                 //写回详细信息

    }

    //用于创建XMLHttpRequest对象

    this.createXmlHttp = function() {

        var xmlHttp = null;

        //根据window.XMLHttpRequest对象是否存在使用不同的创建方式

        if (window.XMLHttpRequest) {

           xmlHttp = new XMLHttpRequest();                             //FireFox、Opera等浏览器支持的创建方式

        } else {

           xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");//IE浏览器支持的创建方式

        }

        return xmlHttp;

    }

    //检查两次输入的密码是否一致

    this.checkPassword = function() {

        var p1 = document.getElementById("password").value;                //获取密码

        var p2 = document.getElementById("password2").value;             //获取验证密码

        //当两部分密码都输入完毕后进行判断

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

            if (p1 != p2) {

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

                                 "0密码验证与密码不一致。");

            } else {

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

            }

        } else if (p1 != null) {

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

        }

    }

}

3.1.7  小结

表单验证在网站中是很常见的内容,可以说只要是用到表单的地方,十有八九需要进行内容验证。当遇到需要提交给服务器才能验证的字段时,使用Ajax技术是一个非常好的选择。本例虽然只讲解了用户注册的表单验证,但其基本思想和实现技术可以推广到各种类型的表单验证中去。

posted on 2009-04-20 12:55 MichaelLee 阅读(2024) 评论(2)  编辑  收藏 所属分类: JavaScript

评论

# re: 注册表单验证(转,如有侵权请联络我马上删除) 2010-08-21 16:53 sdfas

asdfasdfasdf  回复  更多评论   

# re: 注册表单验证(转,如有侵权请联络我马上删除) 2010-08-21 16:53 sdfas

sdfasdfa  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 
<2009年4月>
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

导航

统计

公告

====Michael Lee====
=Java Sofware Engineer=
=Work @ Beijing=
---再烦,也别忘微笑;再急,也要注意语气;再苦,也别忘坚持;再累,也要爱自己!---
---低调做人,你会一次比一次稳健;高调做事,你会一次比一次优秀---
---成功的时候不要忘记过去;失败的时候不要忘记还有未来---

常用链接

留言簿(2)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜