真没想到,一个小小的注册登陆程序竟然出了这么多bug,这次真是脸丢大了。
先来看看sql注入是怎么回事,其实利用欣欣的密码,确实可以随便一个帐号就能登陆,这个密码被称作万能密码,比如用户名填notexist,密码填11' or '1'='1,那么最终执行的sql语句就变成:select * from test where username='notexist' and passwd='11' or '1'='1';,这样的话'1'='1'永远是真,也就全都选出来啦,比较靠谱的方法是,先根据用户名选出记录,再判断密码对不对,这样可以防止sql注入。
然后我们来看看session是怎么回事,其实session是服务器为每个会话保存的一小块内存,那么什么是会话呢?简单说,就是我们打开一个浏览器,去访问一个网站,这就是一个会话,直到我们关闭浏览器为止。
我们来做一个实验:做三个页面,put_session.php往session中放东西,get_session.php获取session,clear_session.php清除session,代码如下:
put_session:
<?php session_start(); $_SESSION['key'] = 'i am session'; ?>check the result
get_session:
<?php session_start(); if(isset($_SESSION['key'])) { echo $_SESSION['key']; } else { echo "no session found"; } ?>check the result
clear_session:
<?php session_start(); unset($_SESSION['key']); ?>check the result
先访问get_session,会发现一开始没有session,再访问put_session,这时向session中放入了东西,这时再访问get_session,就看到东西啦,要想清除session,就访问下clear_session,然后再刷新get_session,东西又没啦。
注意,在php中操作session,一定要先调用session_start()方法,然后就可以通过$_SESSION来操作session了。
这下我们就可以修复原来的3个bug啦,修复后的代码如下:
login.php:
<form action="handler.php" method="post"> <input type="text" name="username" placeholder="请输入用户名" /><br/> <input type="password" name="password" placeholder="请输入密码" /><br/> <input type="hidden" name="type" value="login" /><br/> <input type="submit" value="登陆" /><br/> </form> 没账号?去<a href="register.php">注册</a>check the result
register.php:
<form action="handler.php" method="post"> <input type="text" name="username" placeholder="请输入用户名" /><br/> <input type="password" name="password" placeholder="请输入密码" /><br/> <input type="hidden" name="type" value="register" /><br/> <input type="submit" value="注册" /><br/> </form> 有账号?直接<a href="login.php">登陆</a>check the result
welcome.php:
<?php session_start(); if(isset($_SESSION['username'])) { echo "欢迎您 : " . $_SESSION['username']; } else { header("Location: login.php"); } ?>
handler.php:
<?php require_once dirname ( __FILE__ ) . '/../../../../common/SQLHelper.class.php'; if(isset($_POST['type'])) { $type = $_POST['type']; if(isset($_POST['username']) && isset($_POST['password'])) { $sqlHelper = new SQLHelper(); $username = $_POST['username']; $password = $_POST['password']; if($type == "login") { $sql = "select * from test where username='". $username . "'"; $res = $sqlHelper->execute_dql_array($sql); if(count($res) > 0) { if($res[0]['passwd'] == $password) { // 密码验证通过 session_start(); $_SESSION['username'] = $username; header("Location: welcome.php"); } else { header("Location: login.php"); } } else { header("Location: login.php"); } } else if($type == "register") { $sql = "select * from test where username='". $username . "'"; $res = $sqlHelper->execute_dql_array($sql); var_dump($res); if(count($res) > 0) { //用户名已存在 header("Location: login.php"); exit(); } $sql = "insert into test (username, passwd) values ('" . $username . "', '" . $password . "')"; $res = $sqlHelper->execute_dqm($sql); if($res == 1) { session_start(); $_SESSION['username'] = $username; header("Location: welcome.php"); } else { header("Location: login.php"); } } } else { header("Location: login.php"); } } else { header("Location: login.php"); } ?>
写后台一定要注意跳转的控制和逻辑,后台最容易出bug,特别是有用户输入的地方,要判断各种情况,很多黑客就是通过输入的时候输入一些特殊东西,破解后台的。