PHP邮箱验证示例教程


Posted in PHP onJune 01, 2016

在用户注册中最常见的安全验证之一就是邮箱验证。根据行业的一般做法,进行邮箱验证是避免潜在的安全隐患一种非常重要的做法,现在就让我们来讨论一下这些最佳实践,来看看如何在PHP中创建一个邮箱验证。

让我们先从一个注册表单开始:

<form method="post" action="http://mydomain.com/registration/">
 <fieldset class="form-group">
 <label for="fname">First Name:</label>
 <input type="text" name="fname" class="form-control" required />
  </fieldset>

  <fieldset class="form-group">
 <label for="lname">Last Name:</label>
 <input type="text" name="lname" class="form-control" required />
  </fieldset>

  <fieldset class="form-group">
 <label for="email">Last name:</label>
 <input type="email" name="email" class="form-control" required />
  </fieldset>

  <fieldset class="form-group">
 <label for="password">Password:</label>
 <input type="password" name="password" class="form-control" required />
  </fieldset>

  <fieldset class="form-group">
 <label for="cpassword">Confirm Password:</label>
 <input type="password" name="cpassword" class="form-control" required />
  </fieldset>

  <fieldset>
    <button type="submit" class="btn">Register</button>
  </fieldset>
</form>

接下来是数据库的表结构:

CREATE TABLE IF NOT EXISTS `user` (
 `id` INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
 `fname` VARCHAR(255) ,
 `lname` VARCHAR(255) ,
 `email` VARCHAR(50) ,
 `password` VARCHAR(50) ,
 `is_active` INT(1) DEFAULT '0',
 `verify_token` VARCHAR(255) ,
 `created_at` TIMESTAMP,
 `updated_at` TIMESTAMP,
);

一旦这个表单被提交了,我们就需要验证用户的输入并且创建一个新用户:

// Validation rules
$rules = array(
  'fname' => 'required|max:255',
  'lname' => 'required|max:255',
 'email' => 'required',
 'password' => 'required|min:6|max:20',
 'cpassword' => 'same:password'
);

$validator = Validator::make(Input::all(), $rules);

// If input not valid, go back to registration page
if($validator->fails()) {
 return Redirect::to('registration')->with('error', $validator->messages()->first())->withInput();
}

$user = new User();
$user->fname = Input::get('fname');
$user->lname = Input::get('lname');
$user->password = Input::get('password');

// You will generate the verification code here and save it to the database

// Save user to the database
if(!$user->save()) {
 // If unable to write to database for any reason, show the error
 return Redirect::to('registration')->with('error', 'Unable to write to database at this time. Please try again later.')->withInput();
}

// User is created and saved to database
// Verification e-mail will be sent here

// Go back to registration page and show the success message
return Redirect::to('registration')->with('success', 'You have successfully created an account. The verification link has been sent to e-mail address you have provided. Please click on that link to activate your account.');

 注册之后,用户的账户仍然是无效的直到用户的邮箱被验证。此功能确认用户是输入电子邮件地址的所有者,并有助于防止垃圾邮件以及未经授权的电子邮件使用和信息泄露。

 整个流程是非常简单的——当一个新用户被创建时,在注册过过程中,一封包含验证链接的邮件便会被发送到用户填写的邮箱地址中。在用户点击邮箱验证链接和确认邮箱地址之前,用户是不能进行登录和使用网站应用的。

 关于验证的链接有几件事情是需要注意的。验证的链接需要包含一个随机生成的token,这个token应该足够长并且只在一段时间段内是有效的,这样做的方法是为了防止网络攻击。同时,邮箱验证中也需要包含用户的唯一标识,这样就可以避免那些攻击多用户的潜在危险。

现在让我们来看看在实践中如何生成一个验证链接:

// We will generate a random 32 alphanumeric string
// It is almost impossible to brute-force this key space
$code = str_random(32);
$user->confirmation_code = $code;

一旦这个验证被创建就把他存储到数据库中,发送给用户:

Mail::send('emails.email-confirmation', array('code' => $code, 'id' => $user->id), function($message)
{
$message->from('my@domain.com', 'Mydomain.com')->to($user->email, $user->fname . ' ' . $user->lname)->subject('Mydomain.com: E-mail confirmation');
});

邮箱验证的内容:

<!DOCTYPE html>
<html lang="en-US">
 <head>
 <meta charset="utf-8" />
 </head>

 <body>
 <p style="margin:0">
  Please confirm your e-mail address by clicking the following link:
  <a href="http://mydomain.com/verify?code=<?php echo $code; ?>&user=<?php echo $id; ?>"></a>
 </p>
 </body>
</html>

现在让我们来验证一下它是否可行:

$user = User::where('id', '=', Input::get('user'))
  ->where('is_active', '=', 0)
  ->where('verify_token', '=', Input::get('code'))
  ->where('created_at', '>=', time() - (86400 * 2))
  ->first();

if($user) {
 $user->verify_token = null;
 $user->is_active = 1;

 if(!$user->save()) {
 // If unable to write to database for any reason, show the error
 return Redirect::to('verify')->with('error', 'Unable to connect to database at this time. Please try again later.');
 }

 // Show the success message
 return Redirect::to('verify')->with('success', 'You account is now active. Thank you.');
}

// Code not valid, show error message
return Redirect::to('verify')->with('error', 'Verification code not valid.');

结论:
上面展示的代码只是一个教程示例,并且没有通过足够的测试。在你的web应用中使用的时候请先测试一下。上面的代码是在Laravel框架中完成的,但是你可以很轻松的把它迁移到其他的PHP框架中。同时,验证链接的有效时间为48小时,之后就过期。引入一个工作队列就可以很好的及时处理那些已经过期的验证链接。

本文实PHPChina原创翻译,原文转载于http://www.phpchina.com/portal.php?mod=view&aid=39888,小编认为这篇文章很具有学习的价值,分享给大家,希望对大家的学习有所帮助。

PHP 相关文章推荐
复杂检索数据并分页显示的处理方法
Oct 09 PHP
PHP session有效期问题
Apr 26 PHP
一些PHP Coding Tips(php小技巧)[2011/04/02最后更新]
May 02 PHP
php 删除目录下N分钟前创建的所有文件的实现代码
Aug 10 PHP
PHP批量查询WordPress留言者E-mail地址实现方法
Feb 15 PHP
文件上传之SWFUpload插件(代码)
Jul 30 PHP
php实现登录tplink WR882N获取IP和重启的方法
Jul 20 PHP
Laravel5.1自定义500错误页面示例
Oct 09 PHP
PHPExcel在linux环境下导出报500错误的解决方法
Jan 26 PHP
PHP中CheckBox多选框上传失败的代码写法
Feb 13 PHP
PHP基于方差和标准差计算学生成绩的稳定性示例
Jul 04 PHP
php中输出json对象的值(实现方法)
Mar 07 PHP
PHP微信公众号自动发送红包API
Jun 01 #PHP
PHP模块化安装教程
Jun 01 #PHP
深入理解PHP之源码目录结构与功能说明
Jun 01 #PHP
基于PHP生成简单的验证码
Jun 01 #PHP
深入理解PHP原理之执行周期分析
Jun 01 #PHP
深入理解PHP之OpCode原理详解
Jun 01 #PHP
深入理解PHP中的count函数
May 31 #PHP
You might like
php中关于codeigniter的xmlrpc的类在进行数据交换时的类型问题
2011/07/03 PHP
常见PHP数据库解决方案分析介绍
2015/09/24 PHP
ThinkPHP5.1框架数据库链接和增删改查操作示例
2019/08/03 PHP
Laravel框架实现的上传图片到七牛功能详解
2019/09/06 PHP
js判断是否为ie的方法小结
2014/01/13 Javascript
js数组依据下标删除元素
2015/04/14 Javascript
JavaScript三元运算符的多种使用技巧
2015/04/16 Javascript
JS基于Mootools实现的个性菜单效果代码
2015/10/21 Javascript
JavaScript 字符串数字左补位,右补位,取固定长度,截位扩展函数代码
2017/03/25 Javascript
微信小程序获取用户openId的实现方法
2017/05/23 Javascript
AngularJS常见过滤器用法实例总结
2017/07/06 Javascript
使用jQuery实现动态添加小广告
2017/07/11 jQuery
vue-router重定向和路由别名的使用讲解
2019/01/19 Javascript
Vue $mount实战之实现消息弹窗组件
2019/04/22 Javascript
小程序云开发获取不到数据库记录的解决方法
2019/05/18 Javascript
Vue插件之滑动验证码
2019/09/21 Javascript
vue中根据时间戳判断对应的时间(今天 昨天 前天)
2019/12/20 Javascript
Python编程实现控制cmd命令行显示颜色的方法示例
2017/08/14 Python
酷! 程序员用Python带你玩转冲顶大会
2018/01/17 Python
python 读取txt中每行数据,并且保存到excel中的实例
2018/04/29 Python
Python利用ORM控制MongoDB(MongoEngine)的步骤全纪录
2018/09/13 Python
python树莓派红外反射传感器
2019/01/21 Python
python在新的图片窗口显示图片(图像)的方法
2019/07/11 Python
Django实现CAS+OAuth2的方法示例
2019/10/30 Python
8种常用的Python工具
2020/08/05 Python
Python 在 VSCode 中使用 IPython Kernel 的方法详解
2020/09/05 Python
英国女鞋购物网站:Moda in Pelle
2019/02/18 全球购物
Java提供了哪些企业应用编程接口
2015/02/13 面试题
英语简历自我评价
2014/01/26 职场文书
运动会广播稿150字
2014/02/19 职场文书
公司寄语大全
2014/04/10 职场文书
奉献演讲稿范文
2014/05/21 职场文书
2014年秋季开学演讲稿
2014/05/24 职场文书
公安机关正风肃纪剖析材料
2014/10/10 职场文书
先进集体事迹材料范文
2014/12/25 职场文书
Python+腾讯云服务器实现每日自动健康打卡
2021/12/06 Python