1、万能的用户名: a' or '1 密码: a' or '1
2、原理:
在将用户名和密码的表单值传入where条件中时,sql语句为: SELECT * FROM adminuser WHERE username='a' or '1' AND password= 'a' or '1'; 这样的话 这个WHERE条件恒成立 一直为true 就能直接登录进去。
3、解决方案:
为了防止出现这种情况,需要对这个用户名密码进行预处理。
在处理页面中,加上一个名为params的数组的参数,WHERE条件中的参数用占位符代替,params数组 各个下标为占位符名称,值则为表单传入的值。
$re = $adminuser->findAll(array('where'=>"username=:u AND password=:p",'params'=>array(":u"=>$username,":p"=>$password)));
...
在Model基类中的findAll方法里,不再直接执行sql语句。而是用pdo类的准备语句
$params = isset($arr['params'])?$arr['params']:array();
$pdoS=$this->pdo->prepare($sql);
if(is_object($pdoS)){
$i=1; //这里设置$i的原因 是为了构建不同的变量,
if($params){
foreach($params as $k => $v){
$name = 'p_'.$i; //由构建出来的这个$name来作为参数名,保存遍历出来的每一个$v的值
$i++;
$$name=$v; //如果不采取这种办法 而直接绑定$v的值的话,会导致每个$k都被绑定上
$pdoS->bindParam($k,$$name); //最后一个$v的值,这样在验证的时候基本不可能通过
}
}
$re = $pdoS->execute();
...
除了以上代码外,还有一种更简便的办法:
$re = $pdoS->execute($params);
...
直接将$params传入execute方法里,节省了绑定参数的过程。
4、动态变量
在以上的内容中,用到了一个概念:动态变量。
$a='abc';
$$a = '123';
echo $abc;
按理来说,我并没有声明$abc变量,但是在$$a中,$a被解析成了abc ,然后就得到了$abc这个变量。
这种用一个变量值去声明另一个变量,这样得到的变量被称为动态变量。基于动态变量,我可以在foreach中,得到不同的变量名来存储每一个$v的值。