今天研究了用PHP发送验证邮件的流程,基本流程是这样的:用户填写完注册信息并提交,后台验证完通过后会向用户邮箱发送一条系统邮件,邮件内容里有一个链接地址,用户进入注册邮箱接收邮件并点击链接即完成用户验证。思路还是很清晰的,而且大部分用户注册网站都是这么处理的。这里有个细节,一般出于GET方式安全考虑,验证码采用密文,通过GET方式获得的密文经解码后再与数据库内的明文验证码比较。有些朋友可能考虑数据库里也存密文,这样就可以直接拿GET到的东西去数据库查询了。这样虽然也方便,但对用户数据不做处理直接进行数据库查询是很危险的做法,因为很有可能在这一环上被黑客利用惨遭sql注入。
PHP发送邮件部分,虽然PHP内置了mail()方法可以方便实现邮件发送,但是对于没有SMTP服务器的个人电脑用户,要配置SMTP程序的话还是比较麻烦。这里推荐使用PHPMailer这个库,利用它你能快速实现功能强大的PHP邮件功能。这里推荐两个博客,php发送邮件原理和使用PHPMailer发送邮件。另外要注意的是,要改一下php.ini的配置;extension=php_openssl.dll和;extension=php_sockets.dll前的;都要去掉以开启这两个模块。
接下来的任务就是加密和解密了。原以为下面就是水到渠成了,未想遇到了大问题。由于要加解密,我首先想到了功能强大的mcrypt库,然后就看到了这篇博客,感觉还挺简单的,就照着写了加密和解密两个方法。打算一个在发验证邮件前用,一个在接收用户点击激活链接后GET回来验证码后用。然后遇到了问题。第一个问题mcrypt_create_iv这个函数实际上通过第二个参数给加密算法引入了随机性,本身有助于提高加密强度。但是我要怎么把加密时生成的这个返回值(假设为$iv)传递给解密方法呢?这个问题一度让我头大,后来在查看官方文档时看到了这句,大致是说可以把mcrypt_create_iv函数的第二个参数设置成全零字符串即“00000000”如果不需要这种随机性的话,虽然不推荐。于是我就忍痛这么干了,“解决”了参数传递问题。其实期间也有考虑过session机制,后来觉得还是不妥。第二个问题更离奇,我试验了“123456789”这样一个验证码,加密后生成一个奇怪的字符串,因为要作为url的一部分,所以对他进行了urlencode编码,生成了这样一个“%15
就在我心灰意冷的时候,准备放弃这个加密方式的时候,看到了另一个加密方法,这个是php内置的base64加密方式,但这个加密方式较单一,也不提供自定义的密钥。不过测试后发现,它生成的密文却比mcrypt加密生成的密文看上去“正常”多,后来灵机一动干脆双重加密好了,先mcrypt生成一个密文,然后继续base6_encode加密生成一个规则的密文,最后urlencode成url格式字符串写入激活链接的url。GET回来后再反向层层解密。最后经测试之前的奇怪现象消失了,得到了最初的明文,哈哈,这个可以有!!完成到这,后面的事情就简单了,就只剩数据库的查询了,而且在查询数据库的时候不用怎么担心在这一环被sql注入。
最后贴上一段代码。
public function encodingVerification(){
$this->load->library("coding");
$arr = $this->coding->encoding();
// var_dump($arr);
// $t = $this->coding->decoding(urldecode(urlencode($arr['encrypted'])));
// echo $t;;
$content = "http://localhost/LocalProject/ciapp/index.php/mail/getVerification?v=".urlencode(base64_encode($arr['encrypted']));
$this->myMail($content);
}
public function decodingVerification($arr){
$this->load->library("coding");
$vcode = $this->coding->decoding($arr);
return $vcode;
}
public function getVerification(){
// echo $_GET['v'];
// echo "\n".urldecode($_GET['v']);
$v = $this->decodingVerification(base64_decode(urldecode($_GET['v'])));
echo "\n".$v;
}