瑞当

瑞当科技
创新引领未来

使用 Perl、jQuery、Ajax、JSON 和 MySQL实现简单的登录

普通网民的主要活动就是网上购物、搜索信息、注册论坛和社区、玩网络游戏,以及在互联网上与其他用户交互。对于大部分这类行为,用户都需要注册并登录网站。需要特别注意这些基本特性;对于用户来说,它们必须简单快速安全。从开发人员的角度来看,由于采用新的技术,实现这些新特性将变得更为简单。

在本文中,您将了解如何将这些技术集合在一起,然后为您的网站实现一个简单的登录特性。

实现过程分为 4 个部分:

  1. SQL 部分 定义了如何创建一个表来将用户信息存储到数据库中。
  2. HTML 部分 实现了 CSS 和 JavaScript 引用以及登录表单。
  3. JavaScript 部分 使用 jQuery 和 JSON 实现了 Ajax 部分。
  4. 最后,Perl 部分 实现用户输入和数据库之间的交互。

在 操作部分,您将找到有关将以上所有部分结合起来的分步操作。本文假设读者熟悉前面提到的技术并具有一定的 web 开发经验。如果您的经验足够丰富的话,可以直接阅读操作部分。

本文未涉及的内容

需要注意的是,本文未涵盖有关安全性的内容,例如,检查用户的输入以排除潜在的数据和系统威胁。因此,也没有介绍有关保存用户密码的加密方法的内容。然而,强烈建议您了解系统的漏洞并在代码中构建相关特性。

SQL

由于本文将介绍的是非常简单的登录特性,因此 users 表只包含 3 个字段;一个唯一的 id,一个唯一的 username 和一个password


清单 1. SQL 代码
				
CREATE TABLE `mydb`.`users` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `username` VARCHAR(45) NOT NULL ,
  `password` VARCHAR(45) NOT NULL ,
  PRIMARY KEY (`id`) ,
  UNIQUE INDEX `id_UNIQUE` (`id` ASC) ,
  UNIQUE INDEX `username_UNIQUE` (`username` ASC)
);
COMMIT;

实际的数据插入和唯一性检验是通过注册特性实现的,因此不属于本文涵盖的内容。我们假设 users 表已经填充了相应的用户信息,这些都是实现登录所必需的。

但是,出于测试考虑,您可能需要使用如下代码向 users 表插入两个简单的条目:

INSERT INTO `mydb`.`users` (`id`, `username`, `password`) 
  VALUES(1, 'username1', 'password1');
INSERT INTO `mydb`.`users` (`id`, `username`, `password`) 
  VALUES(2, 'username2', 'password2');
COMMIT;

如果使用的不是 MySQL,那么您的数据的 SQL 语法可能和 MySQL 的语法稍微有些不同。

HTML

HTML 文件包含登录表单、CSS 和 JavaScript 文件引用。

CSS 引用

为了保持简单性,本文将更多地侧重于以上技术的实现而不是登录表单的设计,因此使用了现成的源和一个修改过的 MIT License,称为 Blueprint CSS 框架,确保浏览器之间的兼容性。当然,互联网上有很多免费的面向不同设计的 CSS 实现。 
参见 参考资料,了解有关 Blueprint 框架的更多信息。

<link rel="stylesheet" type="text/css" media="screen, projection" 
  href="http://www.blueprintcss.org/blueprint/screen.css" />
<link rel="stylesheet"  type="text/css" media="screen, projection"
  href="http://www.blueprintcss.org/blueprint/plugins/buttons/screen.css" />
<link rel="stylesheet" type="text/css" media="print" 
  href="http://www.blueprintcss.org/blueprint/print.css" />
<!--[if IE]><link rel="stylesheet" type="text/css" media="screen, projection" 
  href="http://www.blueprintcss.org/blueprint/ie.css"><![endif]-->

JavaScript 引用

除了 jQuery 库外,还存在对 JavaScript 文件的引用(login.js),本文稍后将解释这一点。

<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="login.js"></script>

在本文撰写之际,jQuery 的版本是 1.4.4,请参见 参考资料,选用最新的版本。

登录表单

登录表单包含一个 username 文本字段、一个 password 字段和一个 submit 按钮。

<form id="loginForm" name="loginForm" method="post" action="">
  <fieldset>
    <legend>Enter information</legend>
    <p>
      <label for="username">Username</label>
      <br />
      <input type="text" id="username" name="username" class="text" size="20" />
    </p>
    <p>
      <label for="password">Password</label>
      <br />
      <input type="password" id="password" name="password" class="text" size="20" />
    </p>
    <p>
      <button type="submit" class="button positive">
       <img alt="ok" src=
       "http://www.blueprintcss.org/blueprint/plugins/buttons/icons/tick.png" /> 
       Login
      </button>
    </p>
  </fieldset>
</form>

将使用一个 Captcha 来测试输入的来源,即测试是人工输入还是由计算机生成。 

登录操作的结果将显示在 div 标记中,该标记在加载期间将隐藏,稍后由 JavaScript 填充。

<div id="loginResult" style="display:none;">
</div>


清单 2. login.html
				
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Very simple login using Perl, jQuery, Ajax, JSON and MySQL</title>
    <link rel="stylesheet" type="text/css" media="screen, projection" 
      href="http://www.blueprintcss.org/blueprint/screen.css" />
    <link rel="stylesheet"  type="text/css" media="screen, projection"
      href="http://www.blueprintcss.org/blueprint/plugins/buttons/screen.css" />
    <link rel="stylesheet" type="text/css" media="print" 
      href="http://www.blueprintcss.org/blueprint/print.css" />
    <!--[if IE]><link rel="stylesheet" type="text/css" media="screen, projection" 
      href="http://www.blueprintcss.org/blueprint/ie.css"><![endif]-->
    <script type="text/javascript" 
      src="http://code.jquery.com/jquery-1.4.4.min.js"></script>
    <script type="text/javascript" src="login.js"></script>
    <style type="text/css">
      #loginContent { width: 350px; margin: 100px auto; }
      button[type] { margin: 0.5em 0; }
    </style>
  </head>
  <body>
    <div id="loginContent" class="container">
      <div id="loginResult" style="display:none;">
      </div>
      <form id="loginForm" name="loginForm" method="post" action="">
        <fieldset>
          <legend>Enter information</legend>
          <p>
            <label for="username">Username</label>
            <br />
            <input type="text" id="username" name="username" class="text" size="20" />
          </p>
          <p>
            <label for="password">Password</label>
            <br />
            <input type="password" id="password" name="password" class="text" size="20" />
          </p>
          <p>
            <button type="submit" class="button positive">
             <img alt="ok" src=
             "http://www.blueprintcss.org/blueprint/plugins/buttons/icons/tick.png" /> 
             Login
            </button>
          </p>
        </fieldset>
      </form>
    </div>
  </body>
</html>

尽管 CSS 并非主要考虑,HTML 代码中仍然包含了额外的两行,用于美化表单和按钮的外观。

HTML 代码和额外的 CSS 定义都已通过 W3C Validation Services 的验证。

参考 参考资料,了解有关 W3C Validation Services 的更多消息。

JavaScript

用户提交登录表单后,jQuery 库将读取输入。然后将进行一个非常简单的测试,检查是否提交了空的字段。之后,将对 Perl 脚本进行一个 Ajax 调用(login.pl)。Ajax 调用的关键是将 dataType 参数设置为 json

根据脚本调用的结果,将调用 error 或 success 函数。在本代码示例中,这两个函数都将结果写入到 div 标记,并使用 loginResultid。

如果失败的话,样例代码将显示 jQuery 提供的 XMLHttpRequest.responseTexttextStatus 和 errorThrown

如果脚本调用成功,那么对它的响应进行测试。如果响应变量 data 没有包含错误消息,那么用户 id 和成功消息都将显示,用户 id 是通过 Perl 脚本从 users 表取回的。如果成功,代码样例将隐藏起来,并只显示 div 标记。

完整的 JavaScript 代码


清单 3. login.js
				
$(document).ready(function(){
  $("form#loginForm").submit(function() { // loginForm is submitted
    var username = $('#username').attr('value'); // get username
    var password = $('#password').attr('value'); // get password

    if (username && password) { // values are not empty
      $.ajax({
        type: "GET",
        url: "/cgi-bin/login.pl", // URL of the Perl script
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        // send username and password as parameters to the Perl script
        data: "username=" + username + "&password=" + password,
        // script call was *not* successful
        error: function(XMLHttpRequest, textStatus, errorThrown) { 
          $('div#loginResult').text("responseText: " + XMLHttpRequest.responseText 
            + ", textStatus: " + textStatus 
            + ", errorThrown: " + errorThrown);
          $('div#loginResult').addClass("error");
        }, // error 
        // script call was successful 
        // data contains the JSON values returned by the Perl script 
        success: function(data){
          if (data.error) { // script returned error
            $('div#loginResult').text("data.error: " + data.error);
            $('div#loginResult').addClass("error");
          } // if
          else { // login was successful
            $('form#loginForm').hide();
            $('div#loginResult').text("data.success: " + data.success 
              + ", data.userid: " + data.userid);
            $('div#loginResult').addClass("success");
          } //else
        } // success
      }); // ajax
    } // if
    else {
      $('div#loginResult').text("enter username and password");
      $('div#loginResult').addClass("error");
    } // else
    $('div#loginResult').fadeIn();
    return false;
  });
});

回页首

Perl

对于一个非常简单的实现,Perl 只需要三个模块;CGI、DBI 和 DBD::mysql。通过使用 CGI 模块,Perl 脚本获取 Ajax 发送的username 和 password 值。然后脚本连接到数据库,发出查询并对给定的值选取用户 id。根据查询结果,JSON 响应将由一个错误消息或一个成功消息和用户 id 构建。Perl 脚本将内容类型设置为 application/json 并使用 JSON 字符串响应 Ajax,字符串由 jQuery 在 data 变量中获取。

完整的 Perl 代码


清单 4. login.pl
				
#!/usr/bin/perl -T
use CGI;
use DBI;
use strict;
use warnings;

# read the CGI params
my $cgi = CGI->new;
my $username = $cgi->param("username");
my $password = $cgi->param("password");

# connect to the database
my $dbh = DBI->connect("DBI:mysql:database=mydb;host=localhost;port=2009",  
  "mydbusername", "mydbpassword") 
  or die $DBI::errstr;

# check the username and password in the database
my $statement = qq{SELECT id FROM users WHERE username=? and password=?};
my $sth = $dbh->prepare($statement)
  or die $dbh->errstr;
$sth->execute($username, $password)
  or die $sth->errstr;
my ($userID) = $sth->fetchrow_array;

# create a JSON string according to the database result
my $json = ($userID) ? 
  qq{{"success" : "login is successful", "userid" : "$userID"}} : 
  qq{{"error" : "username or password is wrong"}};

# return JSON string
print $cgi->header(-type => "application/json", -charset => "utf-8");
print $json;

代码验证

要构建有效的 JSON 响应,可能需要使用一个 JSON 验证器。
参见 参考资料,了解有关 JSON 验证的更多消息。

显示生成的 JSON 字符串

可以在您的浏览器中检查 JSON 字符串:

  1. 将 $cgi->header(-type => "application/json", -charset => "utf-8"); 修改为 print $cgi->header;
  2. 在浏览器中输入 http://your-domain-name_or_localhost/cgi-bin/login.pl?username=username1&password=password1

操作

  1. 使用 SQL 代码 创建 users 表(将 mydb 修改为合适的值),然后用一些测试数据填充表。
  2. 复制并粘贴 login.html 和 login.js 到 web 服务器的 htdocs 文件夹。文件夹的名称可能会因为 web 服务器的设置而不同。
  3. 复制并粘贴 login.pl 到 web 服务器的 cgi-bin 文件夹。文件夹的名称可能会因为 web 服务器的设置而不同。
  4. 根据您的版本修改 Perl 脚本的第一行(大多数情况下,Unix 为 #!/usr/bin/perl,Windows 为 #!\Perl\bin\perl.exe),并将 mydblocalhost2009mydbusername 和 mydbpassword 修改为适当的值。
  5. 在浏览器中输入 http://your-domain-name_or_localhost/login.html。
  6. 输入正确和错误的用户名和密码,检查不同的输出。

注意

确保将 HTML、JavaScript 和 Perl 文件放到相同的域。否则,当 Ajax 尝试调用与调用脚本不在同一个域中的 Perl 脚本时,将违背同源策略,因此会出现一个错误(data 变量为 null)。此外,出于同样的考虑,HTML 文件必须由 web 文件处理。
参见 参考资料,了解更多有关同源策略的信息。

结束语

本文的目的是教您使用现代技术实现真正简单的代码,您可以以此为起点实现一个登录服务。您可以在此基础上实现更多出色的特性,包括安全性。有了构思之后,您甚至需要使用其他数据库和编程语言。