PHP CodeIgniter框架密码比对if语句执行逻辑异常问题
问题复现
你在登录验证环节执行如下代码做密码比对时,视觉上两个密码完全一致但始终进入else分支:
$model=new CrudModel(); $users = $model->where('Name', $_POST['Name'])->findAll(); if($_POST['Password'] == $users[0]['Password']){ echo 'Pasword is OK'; } else{ print_r($users); echo "<br>"; echo $users[0]['Password'].' --- This is from database'; echo "<br>"; echo $_POST['Password'].' --- This is from user login form'; echo "<br>"; echo 'pasword is not OK'; }
运行结果截图:
问题原因
1. 不可见空白字符干扰
90%以上的这类问题都是这个原因:两个字符串中其中一端前后存在换行、制表符、非断空格这类不可见字符,这类字符打印到HTML页面时会被浏览器自动忽略,所以视觉上看不出差异。最常见的场景是数据库密码字段用了char类型而非varchar,存储时会自动在字符串末尾补空格凑足字段长度。
2. 编码不一致
用户提交的密码和数据库存储的密码编码格式不统一,比如存在全角/半角字符差异、特殊字符转义异常的问题。
3. 模型字段隐式处理
如果你的CrudModel配置了字段修改器、或者开启了自动转义/加密逻辑,存入数据库的密码会存在你没注意到的隐式修改。
排查方法
在else分支中加入两行长度校验代码,确认是否是不可见字符导致的:
echo strlen($_POST['Password']).' --- 提交密码长度'; echo "<br>"; echo strlen($users[0]['Password']).' --- 数据库密码长度';
如果输出的两个长度数值不一致,就可以确认是不可见字符的问题。你也可以直接临时改成trim后比对验证:
if(trim($_POST['Password']) == trim($users[0]['Password']))
如果修改后判断正常进入if分支,就可以锁定是空白字符导致的问题。
修复方案
- 字段类型调整:把数据库密码字段的类型从char改为varchar,避免存储时自动补空格。
- 比对处理:如果不方便改字段,比对时主动对两个值做trim处理后再比对。
- 安全优化(强烈建议):不要明文存储密码、不要直接做明文比对。CodeIgniter支持官方密码哈希能力,存入数据库前用
password_hash()处理密码,验证时用内置方法比对:
if(password_verify($_POST['Password'], $users[0]['Password'])){ // 验证通过逻辑 }
这种方式既更安全,也能规避掉很多不必要的字符串比对异常问题。
内容的提问来源于stack exchange,提问作者Usama Jalal
相关产品推荐
相关产品推荐

