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 相关文章推荐
php4的session功能评述(一)
Oct 09 PHP
浅谈web上存漏洞及原理分析、防范方法(安全文件上存方法)
Jun 29 PHP
PHP生成迅雷、快车、旋风等软件的下载链接代码实例
May 12 PHP
Linux下PHP加速器APC的安装与配置笔记
Oct 24 PHP
php计算title标题相似比的方法
Jul 29 PHP
PHP实现获取文件后缀名的几种常用方法
Aug 08 PHP
100行PHP代码实现socks5代理服务器
Apr 28 PHP
php执行多个存储过程的方法【基于thinkPHP】
Nov 08 PHP
详解PHP文件的自动加载(autoloading)
Feb 04 PHP
PHP正则验证字符串是否为数字的两种方法并附常用正则
Feb 27 PHP
laravel框架之数据库查出来的对象实现转化为数组
Oct 23 PHP
详细分析PHP7与PHP5区别
Jun 26 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
《一拳超人》埼玉一拳下去,他们存在了800年毫无意义!
2020/03/02 日漫
PHP实现网上点歌(二)
2006/10/09 PHP
phpmyadmin导入(import)文件限制的解决办法
2009/12/11 PHP
php基于Snoopy解析网页html的方法
2015/07/09 PHP
Javascript 异步加载详解(浏览器在javascript的加载方式)
2012/05/20 Javascript
分析Node.js connect ECONNREFUSED错误
2013/04/09 Javascript
thinkphp中常用的系统常量和系统变量
2014/03/05 Javascript
JavaScript中判断页面关闭、页面刷新的实现代码
2014/08/27 Javascript
JavaScript数据结构与算法之栈详解
2015/03/12 Javascript
jQuery实现获取绑定自定义事件元素的方法
2015/12/02 Javascript
jquery.serialize() 函数语法及简单实例
2016/07/08 Javascript
探讨AngularJs中ui.route的简单应用
2016/11/16 Javascript
深入理解javascript的getTime()方法
2017/02/16 Javascript
BootStrap实现鼠标悬停下拉列表功能
2017/02/17 Javascript
Vue实现路由跳转和嵌套
2017/06/20 Javascript
js html实现计算器功能
2018/11/13 Javascript
element的el-table中记录滚动条位置的示例代码
2019/11/06 Javascript
在vue中封装的弹窗组件使用队列模式实现方法
2020/07/23 Javascript
通过python下载FTP上的文件夹的实现代码
2013/02/10 Python
python 将字符串转换成字典dict
2013/03/24 Python
对Tensorflow中的变量初始化函数详解
2018/07/27 Python
Python数据类型之Dict字典实例详解
2019/05/07 Python
一篇文章彻底搞懂Python中可迭代(Iterable)、迭代器(Iterator)与生成器(Generator)的概念
2019/05/13 Python
python flask中动态URL规则详解
2019/11/22 Python
python通过移动端访问查看电脑界面
2020/01/06 Python
python 发送邮件的示例代码(Python2/3都可以直接使用)
2020/12/03 Python
HTML5 本地存储之如果没有数据库究竟会怎样
2013/04/25 HTML / CSS
美国皮靴公司自1863年:The Frye Company
2016/11/30 全球购物
教学器材管理制度
2014/01/26 职场文书
石油大学毕业生自荐信
2014/01/28 职场文书
党员教师一句话承诺
2014/05/30 职场文书
新闻发布会活动策划方案
2014/09/15 职场文书
2014超市收银员工作总结
2014/11/13 职场文书
教师师德表现自我评价
2015/03/05 职场文书
小学班长竞选稿
2015/11/20 职场文书
七年级英语教学反思
2016/02/15 职场文书