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 相关文章推荐
Adodb的十个实例(清晰版)
Dec 31 PHP
PHP访问MYSQL数据库封装类(附函数说明)
Dec 04 PHP
php中关于普通表单多文件上传的处理方法
Mar 25 PHP
PHP生成Gif图片验证码
Oct 27 PHP
标准PHP的AES加密算法类
Mar 12 PHP
PHP扩展框架之Yaf框架的安装与使用
May 18 PHP
功能强大的php文件上传类
Aug 29 PHP
PHP CodeIgniter分页实例及多条件查询解决方案(推荐)
May 20 PHP
PHP7扩展开发之hello word实现方法详解
Jan 15 PHP
PHP实现负载均衡session共享redis缓存操作示例
Aug 22 PHP
PHP封装的验证码工具类定义与用法示例
Aug 22 PHP
thinkPHP5.1框架路由::get、post请求简单用法示例
May 06 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
Yii学习总结之数据访问对象 (DAO)
2015/02/22 PHP
PHP实现多维数组转字符串和多维数组转一维数组的方法
2015/08/08 PHP
PHP中子类重载父类的方法【parent::方法名】
2016/05/06 PHP
phpMyAdmin无法登陆的解决方法
2017/04/27 PHP
实例详解jQuery结合GridView控件的使用方法
2016/01/04 Javascript
Angular ng-repeat 对象和数组遍历实例
2016/09/14 Javascript
jQuery模拟实现的select点击选择效果【附demo源码下载】
2016/11/09 Javascript
JavaScript中数据类型转换总结
2016/12/25 Javascript
Bootstrap显示与隐藏简单实现代码
2017/03/06 Javascript
React-Native左右联动List的示例代码
2017/09/21 Javascript
vue实现todolist功能、todolist组件拆分及todolist的删除功能
2019/04/11 Javascript
vue 实现Web端的定位功能 获取经纬度
2019/08/08 Javascript
解决layui追加或者动态修改的表单元素“没效果”的问题
2019/09/18 Javascript
微信小程序列表时间戳转换实现过程解析
2019/10/12 Javascript
VUE实现Studio管理后台之鼠标拖放改变窗口大小
2020/03/04 Javascript
[01:24]2014DOTA2 TI第二日 YYF表示这届谁赢都有可能
2014/07/11 DOTA
用Python和MD5实现网站挂马检测程序
2014/03/13 Python
在Python中使用HTMLParser解析HTML的教程
2015/04/29 Python
Python学习小技巧之列表项的排序
2017/05/20 Python
Python数据结构之双向链表的定义与使用方法示例
2018/01/16 Python
python3之模块psutil系统性能信息使用
2018/05/30 Python
使用sklearn之LabelEncoder将Label标准化的方法
2018/07/11 Python
python 使用matplotlib 实现从文件中读取x,y坐标的可视化方法
2019/07/04 Python
Django rstful登陆认证并检查session是否过期代码实例
2019/08/13 Python
python 实现rolling和apply函数的向下取值操作
2020/06/08 Python
keras输出预测值和真实值方式
2020/06/27 Python
python 获取计算机的网卡信息
2021/02/18 Python
深入理解css中vertical-align属性
2017/04/18 HTML / CSS
html5指南-1.html5全局属性(html5 global attributes)深入理解
2013/01/07 HTML / CSS
HTML5 window/iframe跨域传递消息 API介绍
2013/08/26 HTML / CSS
HTML5中的autofocus(自动聚焦)属性介绍
2014/04/23 HTML / CSS
《梅兰芳学艺》教学反思
2014/02/24 职场文书
环保公益策划方案
2014/08/15 职场文书
学习型家庭事迹材料(2016精选版)
2016/02/29 职场文书
2016学校先进集体事迹材料
2016/02/29 职场文书
详解MySQL数据库千万级数据查询和存储
2021/05/18 MySQL