EasySwoole 驗(yàn)證碼組件
EasySwoole
提供了獨(dú)立的 驗(yàn)證碼組件
,幾行代碼即可實(shí)現(xiàn)輸出一個(gè)驗(yàn)證碼,支持用戶自定義驗(yàn)證碼字體
組件要求
- php: >=7.1
- ext-gd: *
- easyswoole/spl: ^1.0
安裝方法
composer require easyswoole/verifycode=3.x
倉庫地址
基本使用
配置
生成驗(yàn)證碼前需要傳入 \EasySwoole\VerifyCode\Conf
的對象實(shí)例,\EasySwoole\VerifyCode\Conf
類實(shí)例化后會有默認(rèn)配置,無需配置也可生成驗(yàn)證碼圖片。
下面是 \EasySwoole\VerifyCode\Conf
類提供的相關(guān)配置方法。
<?php
// +----------------------------------------------------------------------
// | easySwoole [ use swoole easily just like echo "hello world" ]
// +----------------------------------------------------------------------
// | WebSite: http://www.fe88.cn
// +----------------------------------------------------------------------
// | Welcome Join QQGroup 853946743
// +----------------------------------------------------------------------
namespace EasySwoole\VerifyCode;
use EasySwoole\Spl\SplBean;
/**
* 驗(yàn)證碼配置文件
* Class VerifyCodeConf
* @author : evalor <master@evalor.cn>
* @package Vendor\VerifyCode
*/
class Conf extends SplBean
{
public $charset = '1234567890AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'; // 字母表
public $useCurve = false; // 混淆曲線
public $useNoise = false; // 隨機(jī)噪點(diǎn)
public $useFont = null; // 指定字體
public $fontColor = null; // 字體顏色
public $backColor = null; // 背景顏色
public $imageL = null; // 圖片寬度
public $imageH = null; // 圖片高度
public $fonts = []; // 額外字體
public $fontSize = 25; // 字體大小
public $length = 4; // 生成位數(shù)
public $mime = MIME::PNG; // 設(shè)置類型
public $temp = '/tmp'; // 設(shè)置緩存目錄
public function setTemp($temp){
if (!is_dir($temp)) mkdir($temp,0755) && chmod($temp,0755);
$this->temp = $temp;
}
/**
* 設(shè)置圖片格式
* @param $MimeType
* @author : evalor <master@evalor.cn>
* @return Conf
*/
public function setMimeType($MimeType)
{
$allowMime = [ MIME::PNG, MIME::GIF, MIME::JPG ];
if (in_array($MimeType, $allowMime)) $this->mime = $MimeType;
return $this;
}
/**
* 設(shè)置字符集
* @param string $charset
* @return Conf
*/
public function setCharset($charset)
{
is_string($charset) && $this->charset = $charset;
return $this;
}
/**
* 開啟混淆曲線
* @param bool $useCurve
* @return Conf
*/
public function setUseCurve($useCurve = true)
{
is_bool($useCurve) && $this->useCurve = $useCurve;
return $this;
}
/**
* 開啟噪點(diǎn)生成
* @param bool $useNoise
* @return Conf
*/
public function setUseNoise($useNoise = true)
{
is_bool($useNoise) && $this->useNoise = $useNoise;
return $this;
}
/**
* 使用自定義字體
* @param string $useFont
* @return Conf
*/
public function setUseFont($useFont)
{
is_string($useFont) && $this->useFont = $useFont;
return $this;
}
/**
* 設(shè)置文字顏色
* @param array|string $fontColor
* @return Conf
*/
public function setFontColor($fontColor)
{
if (is_string($fontColor)) $this->fontColor = $this->HEXToRGB($fontColor);
if (is_array($fontColor)) $this->fontColor = $fontColor;
return $this;
}
/**
* 設(shè)置背景顏色
* @param null $backColor
* @return Conf
*/
public function setBackColor($backColor)
{
if (is_string($backColor)) $this->backColor = $this->HEXToRGB($backColor);
if (is_array($backColor)) $this->backColor = $backColor;
return $this;
}
/**
* 設(shè)置圖片寬度
* @param int|string $imageL
* @return Conf
*/
public function setImageWidth($imageL)
{
$this->imageL = intval($imageL);
return $this;
}
/**
* 設(shè)置圖片高度
* @param null $imageH
* @return Conf
*/
public function setImageHeight($imageH)
{
$this->imageH = intval($imageH);
return $this;
}
/**
* 設(shè)置字體集
* @param array|string $fonts
* @return Conf
*/
public function setFonts($fonts)
{
if (is_string($fonts)) array_push($this->fonts, $fonts);
if (is_array($fonts) && !empty($fonts)) {
if (empty($this->fonts)) {
$this->fonts = $fonts;
} else {
array_merge($this->fonts, $fonts);
}
}
return $this;
}
/**
* 設(shè)置字體尺寸
* @param int $fontSize
* @return Conf
*/
public function setFontSize($fontSize)
{
$this->fontSize = intval($fontSize);
return $this;
}
/**
* 設(shè)置驗(yàn)證碼長度
* @param int $length
* @return Conf
*/
public function setLength($length)
{
$this->length = intval($length);
return $this;
}
/**
* 獲取配置值
* @param $name
* @author : evalor <master@evalor.cn>
* @return mixed
*/
public function __get($name)
{
return $this->$name;
}
/**
* 十六進(jìn)制轉(zhuǎn)RGB
* @param $hexColor
* @author : evalor <master@evalor.cn>
* @return array
*/
function HEXToRGB($hexColor)
{
$color = str_replace('#', '', $hexColor);
if (strlen($color) > 3) {
$rgb = array(
hexdec(substr($color, 0, 2)),
hexdec(substr($color, 2, 2)),
hexdec(substr($color, 4, 2))
);
} else {
$color = $hexColor;
$r = substr($color, 0, 1) . substr($color, 0, 1);
$g = substr($color, 1, 1) . substr($color, 1, 1);
$b = substr($color, 2, 1) . substr($color, 2, 1);
$rgb = array(
hexdec($r),
hexdec($g),
hexdec($b)
);
}
return $rgb;
}
}
配置方法
需要對驗(yàn)證碼進(jìn)行自定義配置可以使用上文提到的組件提供的 \EasySwoole\VerifyCode\Conf
類進(jìn)行動(dòng)態(tài)配置。
use EasySwoole\VerifyCode\Conf;
$Conf = new Conf();
設(shè)置字符集合
可以自定義驗(yàn)證碼生成時(shí)使用的字符集合,設(shè)置后從集合中隨機(jī)選取,不設(shè)置則從 [0-9A-Za-z]
中隨機(jī)選取
$Conf->setCharset('123456ABCD');
設(shè)置背景色
設(shè)置驗(yàn)證碼的背景顏色,不設(shè)置則默認(rèn)使用白色,支持使用完整 HEX、縮寫 HEX 和 RGB 值設(shè)置
$Conf->setBackColor('#3A5FCD');
$Conf->setBackColor('CCC');
$Conf->setBackColor([30, 144, 255]);
設(shè)置文字顏色
設(shè)置驗(yàn)證碼的文字顏色,不設(shè)置則隨機(jī)生成一個(gè)顏色,支持使用完整 HEX、縮寫 HEX 和 RGB 值設(shè)置
$Conf->setFontColor('#3A5FCD');
$Conf->setFontColor('CCC');
$Conf->setFontColor([30, 144, 255]);
設(shè)置混淆
支持兩種混淆方式,默認(rèn)兩種混淆都是關(guān)閉的,需要手動(dòng)開啟
// 開啟或關(guān)閉混淆曲線
$Conf->setUseCurve();
// 開啟或關(guān)閉混淆噪點(diǎn)
$Conf->setUseNoise();
設(shè)置字體
默認(rèn)驗(yàn)證碼類已經(jīng)帶有 6 種字體,如果需要增加自己的字體庫來提高識別難度,或者指定使用的字體,可以進(jìn)行如下設(shè)置,注意字體路徑需要使用絕對路徑,即文件的完整路徑
// 增加單個(gè)字體傳入路徑字符串
$Conf->setFonts('path/to/file.ttf');
// 增加多個(gè)字體傳入路徑的數(shù)組
$Conf->setFonts(['path/to/file1.ttf', 'path/to/file2.ttf']);
// 指定生成使用的字體文件
$Conf->setUseFont('path/to/file.ttf');
其他設(shè)置
可以指定驗(yàn)證碼圖片寬高,字體大小,隨機(jī)生成的驗(yàn)證碼位數(shù)等
// 設(shè)置驗(yàn)證碼圖片的寬度
$Conf->setImageWidth(400);
// 設(shè)置驗(yàn)證碼圖片的高度
$Conf->setImageHeight(200);
// 設(shè)置生成字體大小
$Conf->setFontSize(30);
// 設(shè)置生成驗(yàn)證碼位數(shù)
$Conf->setLength(4);
鏈?zhǔn)秸{(diào)用
為了更流暢的進(jìn)行設(shè)置,所有的配置項(xiàng)均支持鏈?zhǔn)秸{(diào)用
$Conf = new Conf();
$Conf->setUseNoise()->setUseCurve()->setFontSize(30);
可以使用上方的動(dòng)態(tài)配置,將設(shè)置好的配置類傳入給驗(yàn)證碼類。
$Conf = new \EasySwoole\VerifyCode\Conf();
$Conf->setFontSize(30);
$VCode = new \EasySwoole\VerifyCode\VerifyCode($Conf);
如果配置比較多,也需要全站統(tǒng)一驗(yàn)證碼配置,可以將驗(yàn)證碼的配置放入配置文件,在生成時(shí)讀取配置,驗(yàn)證碼的配置類繼承自
\EasySwoole\Spl\SplBean
,可以在設(shè)置好后使用配置類的toArray
方法直接獲得配置數(shù)組,實(shí)例化驗(yàn)證碼時(shí),讀取數(shù)組重新生成\EasySwoole\VerifyCode\Conf
類即可。
驗(yàn)證碼生成
\EasySwoole\VerifyCode\VerifyCode
驗(yàn)證碼操作類,如果不傳入 \EasySwoole\VerifyCode\Conf
實(shí)例,則自動(dòng)實(shí)例化一個(gè) \EasySwoole\VerifyCode\Conf
實(shí)例。
<?php
$config = new \EasySwoole\VerifyCode\Conf([
// 以下配置均為可選配置,用戶可根據(jù)需求自行配置
# 'charset' => '1234567890AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz', # 設(shè)置驗(yàn)證碼字符集合,默認(rèn)為 數(shù)字 + 大小寫字母
# 'useCurve' => false, # 設(shè)置不開啟 混淆曲線,默認(rèn)不開啟
# 'useNoise' => false, # 設(shè)置不開啟 隨機(jī)噪點(diǎn),默認(rèn)不開啟
# 'useFont' => null, # 設(shè)置驗(yàn)證碼使用的字體,默認(rèn)隨機(jī)獲取內(nèi)置字體
# 'fontColor' => null, # 設(shè)置 字體顏色,默認(rèn)隨機(jī)獲取,支持使用完整 HEX,縮寫 HEX 和 RGB 值設(shè)置
# 'backColor' => null, # 設(shè)置 背景顏色,默認(rèn)白色,支持使用完整 HEX,縮寫 HEX 和 RGB 值設(shè)置
# 'imageL' => null, # 設(shè)置 驗(yàn)證碼寬度,默認(rèn) 162.5px
# 'imageH' => null, # 設(shè)置 驗(yàn)證碼高度,默認(rèn) 50px
# 'fonts' => [], # 設(shè)置 驗(yàn)證碼可能使用的字體集合,默認(rèn)組件內(nèi)置支持 5 種
# 'fontSize' => 25, # 設(shè)置 驗(yàn)證碼字體大小,默認(rèn) 25px
# 'length' => 4, # 設(shè)置 驗(yàn)證碼位數(shù),默認(rèn) 4 位
]);
# 使用方法單獨(dú)配置 和 上述在構(gòu)造函數(shù)中配置 等價(jià)
// 設(shè)置驗(yàn)證碼長度為 4 【其他配置方法請看上文 \EasySwoole\VerifyCode\Conf 類】
# $config->setLength(4);
$code = new \EasySwoole\VerifyCode\VerifyCode($config);
$code->DrawCode();// 生成驗(yàn)證碼,返回一個(gè) \EasySwoole\VerifyCode\Result 對象
驗(yàn)證碼結(jié)果類
驗(yàn)證碼結(jié)果類,由 VerifyCode
驗(yàn)證碼操作類調(diào)用 DrawCode()
方法時(shí)創(chuàng)建并返回。
下面是 \EasySwoole\VerifyCode\Result
類的具體實(shí)現(xiàn),可獲取創(chuàng)建驗(yàn)證碼之后得到相關(guān)結(jié)果。
<?php
// +----------------------------------------------------------------------
// | easySwoole [ use swoole easily just like echo "hello world" ]
// +----------------------------------------------------------------------
// | WebSite: http://www.fe88.cn
// +----------------------------------------------------------------------
// | Welcome Join QQGroup 853946743
// +----------------------------------------------------------------------
namespace EasySwoole\VerifyCode;
/**
* 驗(yàn)證碼結(jié)果類
* Class Result
* @author : evalor <master@evalor.cn>
* @package easySwoole\VerifyCode
*/
class Result
{
private $captchaByte; // 驗(yàn)證碼圖片
private $captchaMime; // 驗(yàn)證碼類型
private $captchaCode; // 驗(yàn)證碼內(nèi)容
private $createTime;
function __construct($Byte, $Code, $Mime)
{
$this->captchaByte = $Byte;
$this->captchaMime = $Mime;
$this->captchaCode = $Code;
$this->createTime = time();
}
function getCreateTime():int
{
return $this->createTime;
}
function getCodeHash($code = null,$time = null)
{
if(!$code){
$code = $this->captchaCode;
}
if(!$time){
$time = $this->createTime;
}
return substr(md5($code.$time),8,16);
}
/**
* 獲取驗(yàn)證碼圖片
* @author : evalor <master@evalor.cn>
* @return mixed
*/
function getImageByte()
{
return $this->captchaByte;
}
/**
* 返回圖片Base64字符串
* @author : evalor <master@evalor.cn>
* @return string
*/
function getImageBase64()
{
$base64Data = base64_encode($this->captchaByte);
$Mime = $this->captchaMime;
return "data:{$Mime};base64,{$base64Data}";
}
/**
* 獲取驗(yàn)證碼內(nèi)容
* @author : evalor <master@evalor.cn>
* @return mixed
*/
function getImageCode()
{
return $this->captchaCode;
}
/**
* 獲取Mime信息
* @author : evalor <master@evalor.cn>
*/
function getImageMime()
{
return $this->captchaMime;
}
}
使用示例
<?php
/**
* Created by PhpStorm.
* User: Apple
* Date: 2018/11/12 0012
* Time: 16:30
*/
namespace App\HttpController;
use EasySwoole\Http\AbstractInterface\Controller;
use EasySwoole\VerifyCode\Conf;
class VerifyCode extends Controller
{
function index()
{
// 配置驗(yàn)證碼
$config = new Conf();
$code = new \EasySwoole\VerifyCode\VerifyCode($config);
// 生成驗(yàn)證碼
$drawCode = $code->DrawCode();
// 獲取生成的驗(yàn)證碼內(nèi)容字符串 string(4) "0rnh"
// 可存儲起來和用戶輸入的驗(yàn)證碼比對
$codeStr = $drawCode->getImageCode();
// 設(shè)置響應(yīng)文件內(nèi)容類型
$this->response()->withHeader('Content-Type','image/png');
// 向客戶端輸出驗(yàn)證碼圖片
$this->response()->write($drawCode->getImageByte());
}
function getBase64()
{
// 配置驗(yàn)證碼
$config = new Conf();
$code = new \EasySwoole\VerifyCode\VerifyCode($config);
// 生成驗(yàn)證碼
$drawCode = $code->DrawCode();
// 獲取生成的驗(yàn)證碼內(nèi)容字符串 string(4) "0rnh"
// 可存儲起來和用戶輸入的驗(yàn)證碼比對
$codeStr = $drawCode->getImageCode();
// 向客戶端輸出驗(yàn)證碼的 base64 編碼,前端可用來生成圖片
$this->response()->write($drawCode->getImageBase64());
}
}
訪問 http://localhost:9501/VerifyCode/index
(示例請求地址) 即可看到驗(yàn)證碼圖片,訪問 http://localhost:9501/VerifyCode/getBase64
(示例請求地址) 即可得到驗(yàn)證碼圖片的 base64
編碼結(jié)果。
進(jìn)階使用
生成二維碼圖片并返回,然后進(jìn)行校驗(yàn)。
首先新建一個(gè)驗(yàn)證碼工具類 \App\Utility\VerifyCodeTools
,內(nèi)容如下所示:
<?php
/**
* User: luffyQAQ
* Date: 2019/9/5 15:29
* Email: <1769360227@qq.com>
*/
namespace App\Utility;
class VerifyCodeTools
{
const DURATION = 5 * 60;
// 校驗(yàn)驗(yàn)證碼
public static function checkVerifyCode($code, $time, $hash)
{
if ($time + self::DURATION < time()) {
return false;
}
$code = strtolower($code);
return self::getVerifyCodeHash($code, $time) == $hash;
}
// 生成驗(yàn)證碼 hash 字符串
public static function getVerifyCodeHash($code, $time)
{
return md5($code . $time);
}
}
生成驗(yàn)證碼及對驗(yàn)證碼進(jìn)行校驗(yàn)。
<?php
/**
* User: luffyQAQ
* Date: 2019/9/5 15:29
* Email: <1769360227@qq.com>
*/
namespace App\HttpController;
use App\Utility\VerifyCodeTools;
use EasySwoole\Http\AbstractInterface\Controller;
use EasySwoole\Http\Message\Status;
use EasySwoole\Utility\Random;
use EasySwoole\VerifyCode\Conf;
class VerifyCode extends Controller
{
static $VERIFY_CODE_TTL = 120;
static $VERIFY_CODE_LENGTH = 4;
// 生成驗(yàn)證碼
public function verifyCode()
{
// 配置驗(yàn)證碼
$config = new Conf();
$code = new \EasySwoole\VerifyCode\VerifyCode($config);
// 獲取隨機(jī)數(shù)(即驗(yàn)證碼的具體值)
$random = Random::character(self::$VERIFY_CODE_LENGTH, '1234567890abcdefghijklmnopqrstuvwxyz');
// var_dump($random); string(4) "m02t"
// 繪制驗(yàn)證碼
$code = $code->DrawCode($random);
// 獲取驗(yàn)證碼的 base64 編碼及設(shè)置驗(yàn)證碼有效時(shí)間
$time = time();
$result = [
'verifyCode' => $code->getImageBase64(), // 得到繪制驗(yàn)證碼的 base64 編碼字符串
'verifyCodeTime' => $time,
];
// 將驗(yàn)證碼加密存儲在 Cookie 中,方便進(jìn)行后續(xù)驗(yàn)證。用戶也可以把驗(yàn)證碼保存在 Session 或者 Redis中,方便后續(xù)驗(yàn)證。
$this->response()->setCookie("verifyCodeHash", VerifyCodeTools::getVerifyCodeHash($random, $time), $time + self::$VERIFY_CODE_TTL, '/');
$this->response()->setCookie('verifyCodeTime', $time, $time + self::$VERIFY_CODE_TTL, '/');
$this->writeJson(Status::CODE_OK, $result, 'success');
}
// 校驗(yàn)驗(yàn)證碼
public function checkVerifyCode()
{
$code = $this->request()->getRequestParam('code');
$verifyCodeHash = $this->request()->getRequestParam('verifyCodeHash');
$verifyCodeTime = $this->request()->getRequestParam('verifyCodeTime');
if (!VerifyCodeTools::checkVerifyCode($code, $verifyCodeTime, $verifyCodeHash)) {
$this->writeJson(Status::CODE_OK, '驗(yàn)證碼錯(cuò)誤!', []);
return false;
}
$this->writeJson(Status::CODE_OK, '驗(yàn)證碼正確!', []);
}
}
調(diào)用對應(yīng)的路徑接口(即訪問 http://localhost:9501/VerifyCode/verifyCode
[示例請求地址]),即可實(shí)現(xiàn)前臺驗(yàn)證碼顯示。在 http://localhost:9501/VerifyCode/checkVerifyCode
[示例請求地址] 接口中傳遞參數(shù)即可校驗(yàn)驗(yàn)證碼是否正確。