学了几个月的php终于有时间来做一个小项目了,做这个小项目之前也考虑了多方面的因素。最后决定做这个角色权限管理系统,一方面练练手一方面复习下web开发的相关知识。本来想弄成专栏的但是后来一想反正就是知识分享就写成普通博客了,为了把东西写的细致我把系统拆分成了一个个的模块。今天分享的是系统的门面---登录/注销模块

开发这个小系统我使用的php版本是5.4,mysql是5.0,开发工具为zend studio

1.登录,这个功能可大可小但是要注意注入sql注入以及一些细节问题

下面开始接触我设计的第一个表,这个表用来存储用户信息,表结构如下

这个表应该是比较简单的一个,正规的开发要注意使用MD5加密密码


2.准备登录界面,我这里就用了最简单的那种,代码如下


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<script type="text/javascript" src="../../js/jquery.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>管理平台</title>
</head>
<script type="text/javascript">
function changeYzm(img){
	img.src="../../captcha.php?date="+new Date();
}
function submitCheck(){
	var username=$("#username").val();
	var password=$("#password").val();
	var yzm=$("#yzm").val();
	
	if(""==username){
		alert("用户名不能为空");
		return false;
	}
	if(""==password){
		alert("密码不能为空");
		return false;
	}
	if(""==yzm){
		alert("验证码不能为空");
		return false;
	}
	
}
</script>
<body>
<center>
<form action="LoginController.php" method="post"  οnsubmit="return submitCheck()">
 <table width="280" cellspacing="0" cellpadding="0" style="margin-top:200px;font-size:14px;background-color:FEB930;" border="0" >
   <tr >
     <td height=45 align="right">用户名:</td>
     <td><input type="text" name="username" id="username"/></td>
   </tr>
   <tr>
      <td height=45 align="right">密码:</td>
     <td><input type="password" name="password" id="password"/></td>
   </tr>
   <tr>
      <td height=45 align="right">验证码:</td>
      <td><input type="text" name="yzm" id="yzm"/></td>
      <td><img src="../../captcha.php" id="img" οnclick="changeYzm(this)"/></td>
   </tr>
   <tr>
      <td height=45 align="right"><input type="submit" value="登录" /></td>
      <td><input type="reset" value="取消"/><input type="hidden" name="method" value="toLogin"/></td>
   </tr>
   <tr>
      <td height=45 align="right"></td>
      <td><font color=red><{$error}></font></td>
   </tr>
 </table>
 </form>
 </center>
</body>
</html>

界面是这个样子

界面虽然简单,要注意不要忘记验证码,这样子可以防止机器人登录还可以减少服务器压力,验证码其实就是一个php页面,我的这个很简单代码如下

<?php
//checkNum.php
session_start();
function random($len)
{
$srcstr="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
mt_srand();//配置乱数种子
$strs="";
for($i=0;$i <$len;$i++){
$strs.=$srcstr[mt_rand(0,35)];
}

return strtoupper($strs);
}
$str=random(4); //随机生成的字符串" title="字符串" >字符串
$width = 50; //验证码图片的宽度
$height = 20; //验证码图片的高度

@header("Content-Type:image/png");
$_SESSION["code"] = $str;
//echo $str;
$im=imagecreate($width,$height);
//背景色
$back=imagecolorallocate($im,0xFF,0xFF,0xFF);
//模糊点颜色
$pix=imagecolorallocate($im,187,230,247);
//字体色
$font=imagecolorallocate($im,41,163,238);
//绘模糊作用的点
mt_srand();
for($i=0;$i <1000;$i++)
{
imagesetpixel($im,mt_rand(0,$width),mt_rand(0,$height),$pix);
}
imagestring($im, 5, 7, 5,$str, $font);
imagerectangle($im,0,0,$width-1,$height-1,$font);
imagepng($im);
imagedestroy($im);
$_SESSION["code"] = $str;

?>


点击更换验证码还要注意缓存的问题,可以在请求的时候加上日期,这样就不会出问题了。使用验证码还要打开画图扩展就是extension=php_gd2.dll


3.代码层次结构

这次的小项目还使用到了smarty,mysqli等所以也要打开mysqli扩展,这个就不多说了。这次还是使用mvc设计模式。下面是项目层次图

controller下面放的就是smarty模板以及控制器文件,别的目录容后再说

4.登录模块对应的实现类如下

//登录验证
	public function loginCheck($username,$password){
		$u=new User();
		$db=new DBUtil();
		$conn=$db->getConnection();
		$base=new BaseDBOperate();
		$sql="select count(id) nums from m_user A where A.username='$username' and A.password='$password'";
		$arr=$base->query($sql, $conn);
		$db->close($conn);
		return $arr[0]["nums"];
	}

里面的工具我最后贴出来


5.处理登录的控制器代码片段,这里就要介绍下系统的入口页面index.php了,这个php做得是就是引导程序进入控制器,这个php是下面这个样子

<?php
 header ('Location:module/controller/LoginController.php?method=loginUI' )
?>

控制器代码如下

<?php

require_once '../controller/libs/Smarty.class.php';
require_once "../impl/UserManagerImpl.class.php";
require_once "../model/User.class.php";
require_once "../impl/RoleManagerImpl.class.php";
header ( 'Content-type: text/html; charset=UTF-8' );
$method = $_REQUEST["method"];
if("toLogin"==$method){
	toLogin();
}
if("loginUI"==$method){
	loginUI();
}
if("logoff"==$method){
	logOff();
}
function toLogin(){
	$yzm=$_POST["yzm"];
	session_start();
	if(strcasecmp($_SESSION["code"], $yzm)==0){
		$username=$_POST["username"];
		$password=$_POST["password"];
		$userManager=new UserManagerImpl();
		$count=$userManager->loginCheck($username, $password);
		if($count>0){
			//查询用户名,角色,姓名,状态并保存在session里
			//header("refresh:5;url=http://www.XX.com");  
			$result=$userManager->getUserMessage($username);
			
			$_SESSION["username"]=$result[0]["username"];
			$_SESSION["role"]=$result[0]["role"];
			$_SESSION["realname"]=$result[0]["realname"];
			$smart = new Smarty ();
			$smart->left_delimiter = "<{";
			$smart->right_delimiter = "}>";
			//指定目标所在目录
			$smart->setTemplateDir("../../manage");
			$smart->display("index.html");
			
		}else{
			$smart = new Smarty ();
			$smart->left_delimiter = "<{";
			$smart->right_delimiter = "}>";
			$smart->assign("error","用户名或密码错误");
			$smart->display("login.html");
		}
	}else{
		$smart = new Smarty ();
		$smart->left_delimiter = "<{";
		$smart->right_delimiter = "}>";
		$smart->assign("error","验证码错误");
		$smart->display("login.html");
	}
}
function loginUI(){
	$smart = new Smarty ();
	$smart->left_delimiter = "<{";
	$smart->right_delimiter = "}>";
	$smart->assign("error","");
	$smart->display("login.html");
}
//注销操作
function logOff(){
	session_start();
	session_destroy();
	$smart = new Smarty ();
	$smart->left_delimiter = "<{";
	$smart->right_delimiter = "}>";
	$smart->assign("error","");
	$smart->display("login.html");
}
?>


登录要处理的最大问题其实就是sql注入,大家看到了吗其实我写的sql语句其实会被sql注入,如果输入的用户名或密码为‘ or 1='1  那么所做的登录就无效了。也有办法解决这个问题那就是mysqli的预处理技术,把上面的loginCheck改为下面这样就行

public function loginCheck($username, $password) {
		$u = new User ();
		$db = new DBUtil ();
		$conn = $db->getConnection ();
		$base = new BaseDBOperate ();
		$sql = "select count(id) nums from m_user A where A.username=? and A.password=?";
		$pstmt = $conn->prepare ( $sql );
		// 绑定参数
		$pstmt->bind_param ( "ss", $username, $password );
		$pstmt->execute ();
		$pstmt->bind_result ( $nums );
		$temp = "";
		while ( $pstmt->fetch () ) {
			$temp = $nums;
		}
		$pstmt->free_result ();
		$pstmt->close ();
		
		$db->close ( $conn );
		return $temp;
	}


这个问题也告诉我们,表面上看起来完美无缺的程序不一定就是安全的.

Logo

快速构建 Web 应用程序

更多推荐