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 相关文章推荐
在PHP中使用Sockets 从Usenet中获取文件
Jan 10 PHP
实战mysql导出中文乱码及phpmyadmin导入中文乱码的解决方法
Jun 11 PHP
PHP定时自动生成静态HTML的实现代码
Jun 20 PHP
php visitFile()遍历指定文件夹函数
Aug 21 PHP
PHP中使用crypt()实现用户身份验证的代码
Sep 05 PHP
解析PHP 5.5 新特性
Jul 02 PHP
php获取数组长度的方法(有实例)
Oct 27 PHP
测试php连接mysql是否成功的代码分享
Jan 24 PHP
PHP图片等比例缩放生成缩略图函数分享
Jun 10 PHP
destoon在360浏览器下出现用户被强行注销的解决方法
Jun 26 PHP
PHP实现针对日期,月数,天数,周数,小时,分,秒等的加减运算示例【基于strtotime】
Apr 19 PHP
Laravel 手动开关 Eloquent 修改器的操作方法
Dec 30 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中使用file_get_contents post数据代码例子
2015/02/13 PHP
PHP扩展程序实现守护进程
2015/04/16 PHP
如何解决PHP无法实现多线程的问题
2015/09/25 PHP
PHP实现微信退款的方法示例
2019/03/26 PHP
JS小框架 fly javascript framework
2009/11/26 Javascript
javascript作用域和闭包使用详解
2014/04/25 Javascript
javascript 小数取整简单实现方式
2014/05/30 Javascript
jQuery简易图片放大特效示例代码
2014/06/09 Javascript
angular.bind使用心得
2015/10/26 Javascript
谷歌showModalDialog()方法不兼容出现对话窗口的解决办法
2016/02/15 Javascript
jQuery获得字体颜色16位码的方法
2016/02/20 Javascript
JavaScript用构造函数如何获取变量的类型名
2016/12/23 Javascript
利用node.js如何搭建一个简易的即时响应服务器
2017/05/28 Javascript
JavaScript实现图片切换效果
2017/08/12 Javascript
vue路由传参页面刷新参数丢失问题解决方案
2019/10/08 Javascript
vue项目打包为APP,静态资源正常显示,但API请求不到数据的操作
2020/09/12 Javascript
vue+vant实现购物车全选和反选功能
2020/11/17 Vue.js
[57:24]LGD vs VGJ.T 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
跟老齐学Python之关于类的初步认识
2014/10/11 Python
浅谈python装饰器探究与参数的领取
2017/12/01 Python
基于Python 装饰器装饰类中的方法实例
2018/04/21 Python
Sanic框架异常处理与中间件操作实例分析
2018/07/16 Python
利用4行Python代码监测每一行程序的运行时间和空间消耗
2020/04/22 Python
Tensorflow之MNIST CNN实现并保存、加载模型
2020/06/17 Python
python 图像增强算法实现详解
2021/01/24 Python
美国美妆网站:B-Glowing
2016/10/12 全球购物
德国化妆品和天然化妆品网上商店:kosmetikfuchs.de
2017/06/09 全球购物
Lentiamo比利时:便宜的隐形眼镜
2020/02/14 全球购物
写自荐信三大法宝
2014/01/24 职场文书
网络编辑求职信
2014/04/30 职场文书
研究生求职自荐书
2014/06/23 职场文书
护士年终考核评语
2014/12/31 职场文书
投标单位介绍信
2015/05/05 职场文书
幼儿园托班开学寄语(2016秋季)
2015/12/03 职场文书
python-for x in range的用法(注意要点、细节)
2021/05/10 Python
CSS实现章节添加自增序号的方法
2021/06/23 HTML / CSS