bztang-admin/app/common/services/mews/captcha/src/Captcha.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).'>';
}
}