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 addslashes和mysql_real_escape_string
Jan 24 PHP
PHP 第三节 变量介绍
Apr 28 PHP
php缓存技术详细总结
Aug 07 PHP
php共享内存段示例分享
Jan 20 PHP
php获取从百度、谷歌等搜索引擎进入网站关键词的方法
Jul 08 PHP
php实现跨域提交form表单的方法【2种方法】
Oct 17 PHP
PHP基于迭代实现文件夹复制、删除、查看大小等操作的方法
Aug 11 PHP
PHP+MySQL使用mysql_num_rows实现模糊查询图书信息功能
May 31 PHP
PHP常用正则表达式精选(推荐)
May 28 PHP
漂亮的thinkphp 跳转页封装示例
Oct 16 PHP
基于ThinkPHP删除目录及目录文件函数
Oct 28 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一些有意思的小区别
2006/12/06 PHP
PHP连接MySQL查询结果中文显示乱码解决方法
2013/10/25 PHP
php strnatcmp()函数的用法总结
2013/11/27 PHP
使用swoole扩展php websocket示例
2014/02/13 PHP
Laravel框架中VerifyCsrfToken报错问题的解决
2017/08/30 PHP
php无限级评论嵌套实现代码
2018/04/18 PHP
PHP 多任务秒级定时器的实现方法
2018/05/13 PHP
50个优秀经典PHP算法大集合 附源码
2020/08/26 PHP
ExtJS GridPanel 根据条件改变字体颜色
2010/03/08 Javascript
juqery 学习之四 筛选查找
2010/11/30 Javascript
javascript判断office版本示例
2014/04/11 Javascript
javascript圆盘抽奖程序实现原理和完整代码例子
2014/06/03 Javascript
js查看一个函数的执行时间实例代码
2015/09/12 Javascript
PassWord输入框代码分享
2016/06/07 Javascript
微信小程序 http请求详细介绍
2016/10/09 Javascript
微信小程序 教程之WXSS
2016/10/18 Javascript
浅谈jquery采用attr修改form表单enctype不起作用的问题
2016/11/25 Javascript
JS实现的样式切换功能tableCSS实例
2016/12/30 Javascript
JS实现电商放大镜效果
2017/08/24 Javascript
JQ图片文件上传之前预览功能的简单实例(分享)
2017/11/12 Javascript
详解Vue结合后台的列表增删改案例
2018/08/21 Javascript
细说Vue组件的服务器端渲染的过程
2019/05/30 Javascript
帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)
2019/08/23 Javascript
浅谈JS中几种轻松处理'this'指向方式
2019/09/16 Javascript
viewer.js一个强大的基于jQuery的图像查看插件(支持旋转、缩放)
2020/04/01 jQuery
浅谈DataFrame和SparkSql取值误区
2018/06/09 Python
使用 Visual Studio Code(VSCode)搭建简单的Python+Django开发环境的方法步骤
2018/12/17 Python
几个适合python初学者的简单小程序,看完受益匪浅!(推荐)
2019/04/16 Python
洛杉矶生活休闲而精致的基础品牌:Mika Jaymes
2018/01/07 全球购物
新加坡最佳婴儿用品店:Mamahood.com.sg
2018/08/26 全球购物
美国环保妈妈、儿童和婴儿用品购物网站:The Tot
2019/11/24 全球购物
StringBuilder和String的区别
2015/05/18 面试题
关于幸福的感言
2015/08/03 职场文书
小学生反邪教心得体会
2016/01/15 职场文书
为什么在foreach循环中JAVA集合不能添加或删除元素
2021/06/11 Java/Android
数据设计之权限的实现
2022/08/05 MySQL