529 lines
11 KiB
PHP
529 lines
11 KiB
PHP
<?php
|
|
namespace app\common\services\mews\captcha\src;
|
|
|
|
/**
|
|
* Laravel 5 Captcha package
|
|
*
|
|
* @copyright Copyright (c) 2015 MeWebStudio
|
|
* @version 2.x
|
|
* @author Muharrem ERİN
|
|
* @contact me@mewebstudio.com
|
|
* @web http://www.mewebstudio.com
|
|
* @date 2015-04-03
|
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
|
*/
|
|
|
|
use app\common\helpers\Cache;
|
|
use app\common\services\Session;
|
|
use Exception;
|
|
use Illuminate\Config\Repository;
|
|
use Illuminate\Hashing\BcryptHasher as Hasher;
|
|
use Illuminate\Filesystem\Filesystem;
|
|
use Illuminate\Support\Facades\Crypt;
|
|
use Illuminate\Support\Str;
|
|
use Intervention\Image\ImageManager;
|
|
|
|
/**
|
|
* Class Captcha
|
|
* @package Mews\Captcha
|
|
*/
|
|
class Captcha
|
|
{
|
|
|
|
/**
|
|
* @var Filesystem
|
|
*/
|
|
protected $files;
|
|
|
|
/**
|
|
* @var Repository
|
|
*/
|
|
protected $config;
|
|
|
|
/**
|
|
* @var ImageManager
|
|
*/
|
|
protected $imageManager;
|
|
|
|
/**
|
|
* @var Session
|
|
*/
|
|
protected $session;
|
|
|
|
/**
|
|
* @var Hasher
|
|
*/
|
|
protected $hasher;
|
|
|
|
/**
|
|
* @var Str
|
|
*/
|
|
protected $str;
|
|
|
|
/**
|
|
* @var ImageManager->canvas
|
|
*/
|
|
protected $canvas;
|
|
|
|
/**
|
|
* @var ImageManager->image
|
|
*/
|
|
protected $image;
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
protected $backgrounds = [];
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
protected $fonts = [];
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
protected $fontColors = [];
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
protected $length = 5;
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
protected $width = 120;
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
protected $height = 36;
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
protected $angle = 15;
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
protected $lines = 3;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
protected $characters;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
protected $text;
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
protected $contrast = 0;
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
protected $quality = 90;
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
protected $sharpen = 0;
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
protected $blur = 0;
|
|
|
|
/**
|
|
* @var bool
|
|
*/
|
|
protected $bgImage = true;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
protected $bgColor = '#ffffff';
|
|
|
|
/**
|
|
* @var bool
|
|
*/
|
|
protected $invert = false;
|
|
|
|
/**
|
|
* @var bool
|
|
*/
|
|
protected $sensitive = false;
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
protected $textLeftPadding = 4;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param Filesystem $files
|
|
* @param Repository $config
|
|
* @param ImageManager $imageManager
|
|
* @param Session $session
|
|
* @param Hasher $hasher
|
|
* @param Str $str
|
|
* @throws Exception
|
|
* @internal param Validator $validator
|
|
*/
|
|
public function __construct(
|
|
Filesystem $files,
|
|
Repository $config,
|
|
ImageManager $imageManager,
|
|
Hasher $hasher,
|
|
Str $str
|
|
)
|
|
{
|
|
$this->files = $files;
|
|
$this->config = $config;
|
|
$this->imageManager = $imageManager;
|
|
$this->hasher = $hasher;
|
|
$this->str = $str;
|
|
$this->characters = config('captcha.characters','2346789abcdefghjmnpqrtuxyzABCDEFGHJMNPQRTUXYZ');
|
|
}
|
|
|
|
/**
|
|
* @param string $config
|
|
* @return void
|
|
*/
|
|
protected function configure($config)
|
|
{
|
|
if ($this->config->has('captcha.' . $config))
|
|
{
|
|
foreach($this->config->get('captcha.' . $config) as $key => $val)
|
|
{
|
|
$this->{$key} = $val;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create captcha image
|
|
*
|
|
* @param string $config
|
|
* @param boolean $api
|
|
* @return ImageManager->response
|
|
*/
|
|
public function create($config = 'default', $api = false ,$platform = false)
|
|
{
|
|
$this->backgrounds = $this->files->files(__DIR__ . '/../assets/backgrounds');
|
|
$this->fonts = $this->files->files(__DIR__ . '/../assets/fonts');
|
|
|
|
if (app()->version() >= 5.5){
|
|
$this->fonts = array_map(function($file) {
|
|
return $file->getPathName();
|
|
}, $this->fonts);
|
|
}
|
|
|
|
$this->fonts = array_values($this->fonts); //reset fonts array index
|
|
|
|
$this->configure($config);
|
|
|
|
$generator = $this->generate($platform);
|
|
$this->text = $generator['value'];
|
|
|
|
$this->canvas = $this->imageManager->canvas(
|
|
$this->width,
|
|
$this->height,
|
|
$this->bgColor
|
|
);
|
|
|
|
if ($this->bgImage)
|
|
{
|
|
$this->image = $this->imageManager->make($this->background())->resize(
|
|
$this->width,
|
|
$this->height
|
|
);
|
|
$this->canvas->insert($this->image);
|
|
}
|
|
else
|
|
{
|
|
$this->image = $this->canvas;
|
|
}
|
|
|
|
if ($this->contrast != 0)
|
|
{
|
|
$this->image->contrast($this->contrast);
|
|
}
|
|
|
|
$this->text();
|
|
|
|
$this->lines();
|
|
|
|
if ($this->sharpen)
|
|
{
|
|
$this->image->sharpen($this->sharpen);
|
|
}
|
|
if ($this->invert)
|
|
{
|
|
$this->image->invert($this->invert);
|
|
}
|
|
if ($this->blur)
|
|
{
|
|
$this->image->blur($this->blur);
|
|
}
|
|
|
|
return $api ? [
|
|
'sensitive' => $generator['sensitive'],
|
|
'key' => $generator['key'],
|
|
'img' => $this->image->encode('data-url')->encoded
|
|
] : $this->image->response('png', $this->quality);
|
|
}
|
|
|
|
/**
|
|
* Image backgrounds
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function background()
|
|
{
|
|
return $this->backgrounds[rand(0, count($this->backgrounds) - 1)];
|
|
}
|
|
|
|
/**
|
|
* Generate captcha text
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function generate($platform)
|
|
{
|
|
$characters = str_split($this->characters);
|
|
|
|
$bag = '';
|
|
for($i = 0; $i < $this->length; $i++)
|
|
{
|
|
$bag .= $characters[rand(0, count($characters) - 1)];
|
|
}
|
|
|
|
$bag = $this->sensitive ? $bag : $this->str->lower($bag);
|
|
|
|
$hash = $this->hasher->make($bag);
|
|
if($platform)
|
|
{
|
|
session(['captcha' => [
|
|
'sensitive' => $this->sensitive,
|
|
'key' => $hash
|
|
]]);
|
|
}else{
|
|
Session::put('captcha', [
|
|
'sensitive' => $this->sensitive,
|
|
'key' => $hash
|
|
]);
|
|
}
|
|
//app图形验证码存储
|
|
if (request()->type == 14 || request()->type == 15) {
|
|
Cache::put('sensitive_' . $hash, $this->sensitive, 10);
|
|
}
|
|
return [
|
|
'value' => $bag,
|
|
'sensitive' => $this->sensitive,
|
|
'key' => $hash
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Writing captcha text
|
|
*/
|
|
protected function text()
|
|
{
|
|
$marginTop = $this->image->height() / $this->length;
|
|
|
|
$i = 0;
|
|
foreach(str_split($this->text) as $char)
|
|
{
|
|
$marginLeft = $this->textLeftPadding + ($i * ($this->image->width() - $this->textLeftPadding) / $this->length);
|
|
|
|
$this->image->text($char, $marginLeft, $marginTop, function($font) {
|
|
$font->file($this->font());
|
|
$font->size($this->fontSize());
|
|
$font->color($this->fontColor());
|
|
$font->align('left');
|
|
$font->valign('top');
|
|
$font->angle($this->angle());
|
|
});
|
|
|
|
$i++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Image fonts
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function font()
|
|
{
|
|
return $this->fonts[rand(0, count($this->fonts) - 1)];
|
|
}
|
|
|
|
/**
|
|
* Random font size
|
|
*
|
|
* @return integer
|
|
*/
|
|
protected function fontSize()
|
|
{
|
|
return rand($this->image->height() - 10, $this->image->height());
|
|
}
|
|
|
|
/**
|
|
* Random font color
|
|
*
|
|
* @return array
|
|
*/
|
|
protected function fontColor()
|
|
{
|
|
if ( ! empty($this->fontColors))
|
|
{
|
|
$color = $this->fontColors[rand(0, count($this->fontColors) - 1)];
|
|
}
|
|
else
|
|
{
|
|
$color = [rand(0, 255), rand(0, 255), rand(0, 255)];
|
|
}
|
|
|
|
return $color;
|
|
}
|
|
|
|
/**
|
|
* Angle
|
|
*
|
|
* @return int
|
|
*/
|
|
protected function angle()
|
|
{
|
|
return rand((-1 * $this->angle), $this->angle);
|
|
}
|
|
|
|
/**
|
|
* Random image lines
|
|
*
|
|
* @return \Intervention\Image\Image
|
|
*/
|
|
protected function lines()
|
|
{
|
|
for($i = 0; $i <= $this->lines; $i++)
|
|
{
|
|
$this->image->line(
|
|
rand(0, $this->image->width()) + $i * rand(0, $this->image->height()),
|
|
rand(0, $this->image->height()),
|
|
rand(0, $this->image->width()),
|
|
rand(0, $this->image->height()),
|
|
function ($draw) {
|
|
$draw->color($this->fontColor());
|
|
}
|
|
);
|
|
}
|
|
return $this->image;
|
|
}
|
|
|
|
/**
|
|
* Captcha check
|
|
*
|
|
* @param $value
|
|
* @return bool
|
|
*/
|
|
public function check($value)
|
|
{
|
|
if (request()->type == 14 || request()->type == 15) {
|
|
$key = request()->key;
|
|
if (!Cache::has('sensitive_' . $key)) {
|
|
return false;
|
|
}
|
|
$sensitive = Cache::get('sensitive_' . $key);
|
|
Cache::forget('sensitive_' . $key);
|
|
} else {
|
|
if (!Session::get('captcha')) {
|
|
return false;
|
|
}
|
|
|
|
$key = Session::get('captcha.key');
|
|
$sensitive = Session::get('captcha.sensitive');
|
|
|
|
Session::clear('captcha');
|
|
}
|
|
if (!$sensitive) {
|
|
$value = $this->str->lower($value);
|
|
|
|
}
|
|
|
|
return $this->hasher->check($value, $key);
|
|
}
|
|
|
|
public function platformCheck($value)
|
|
{
|
|
if ( ! session('captcha'))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$key = session('captcha')['key'];
|
|
$sensitive = session('captcha')['sensitive'];
|
|
|
|
if ( ! $sensitive)
|
|
{
|
|
$value = $this->str->lower($value);
|
|
|
|
}
|
|
|
|
request()->session()->forget('captcha');
|
|
|
|
return $this->hasher->check($value, $key);
|
|
}
|
|
|
|
/**
|
|
* Captcha check
|
|
*
|
|
* @param $value
|
|
* @return bool
|
|
*/
|
|
public function check_api($value, $key)
|
|
{
|
|
return $this->hasher->check($value, $key);
|
|
}
|
|
|
|
/**
|
|
* Generate captcha image source
|
|
*
|
|
* @param null $config
|
|
* @return string
|
|
*/
|
|
public function src($config = null)
|
|
{
|
|
return url('captcha' . ($config ? '/' . $config : '/default')) . '?' . $this->str->random(8);
|
|
}
|
|
|
|
/**
|
|
* Generate captcha image html tag
|
|
*
|
|
* @param null $config
|
|
* @param array $attrs HTML attributes supplied to the image tag where key is the attribute
|
|
* and the value is the attribute value
|
|
* @return string
|
|
*/
|
|
public function img($config = null, $attrs = [])
|
|
{
|
|
$attrs_str = '';
|
|
foreach($attrs as $attr => $value){
|
|
if ($attr == 'src'){
|
|
//Neglect src attribute
|
|
continue;
|
|
}
|
|
$attrs_str .= $attr.'="'.$value.'" ';
|
|
}
|
|
return '<img src="' . $this->src($config) . '" '. trim($attrs_str).'>';
|
|
}
|
|
|
|
}
|