You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
3.1 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\ImageCaptcha;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Yo;
class ImageCaptchaController extends Controller
{
public function check($hash, $code, $time, $uuid)
{
$code = mb_strtoupper($code);
$captcha = ImageCaptcha::where('uuid', $uuid)->first();
if ($captcha) return 100005;
if (time() - $time > 60 * 3) return 100005;
if (Hash::check($code . ',Captcha,' . $uuid . ',' . $time, $hash)) {
$captcha = new ImageCaptcha();
$captcha->uuid = $uuid;
$captcha->save();
return 0;
} else {
return 100006;
}
}
public function create()
{
$captcha = $this->generateCaptcha();
$imageBase64 = $this->getImageBase64($captcha['image']);
$time = time();
$uuid = Str::orderedUuid();
$code = mb_strtoupper($captcha['code']);
$hash = Hash::make($code . ',Captcha,' . $uuid . ',' . $time);
$ret = [
'image' => $imageBase64,
'hash' => $hash,
'time' => $time,
'uuid' => $uuid,
];
if (app()->isLocal()) {
$ret['code'] = $code;
$ret['account'] = 'admin';
$ret['password'] = '000000';
}
return Yo::echo($ret);
}
private function generateCaptcha()
{
$code = $this->generateRandomCode();
$image = $this->generateImage($code);
return [
'code' => $code,
'image' => $image
];
}
private function generateRandomCode()
{
$code = '';
$characters = '34acdefhkmnprstwxyACDEFGHKMNPQRWXY';
for ($i = 0; $i < 6; $i++) {
$code .= $characters[rand(0, strlen($characters) - 1)];
}
return $code;
}
private function generateImage($code)
{
$draw_width = 120;
$draw_height = 40;
$image = imagecreate($draw_width, $draw_height);
imagecolorallocate($image, 255, 255, 255);
for ($i = 0; $i < 100; $i++) {
$x = rand(0, 120);
$y = rand(0, 40);
$color = imagecolorallocate($image, rand(0, 255), rand(0, 255), rand(0, 255));
imagesetpixel($image, $x, $y, $color);
}
for ($i = 0; $i < 5; $i++) {
$x1 = rand(0, 120);
$y1 = rand(0, 40);
$x2 = rand(0, 120);
$y2 = rand(0, 40);
$color = imagecolorallocate($image, rand(0, 255), rand(0, 255), rand(0, 255));
imageline($image, $x1, $y1, $x2, $y2, $color);
}
$font_file = 'assets/captcha.ttf';
$original_path = Storage::disk('public')->path($font_file);
$code_size = 26;
for ($i = 0; $i < mb_strlen($code); $i++) {
$c = mb_substr($code, $i, 1);
$r = rand(-20, 20);
$c_box = imagettfbbox($code_size, $r, $original_path, $c);
imagettftext($image, $code_size, $r, 2 + ceil((18 - $c_box[2]) / 2) + (18 * $i), ceil(($draw_height - $c_box[5]) / 2),
imagecolorallocate($image, rand(0, 200), rand(0, 200), rand(0, 200)), $original_path, $c);
}
ob_start();
imagepng($image);
$imageData = ob_get_clean();
return $imageData;
}
private function getImageBase64($imageData)
{
$imageBase64 = base64_encode($imageData);
return 'data:image/png;base64,' . $imageBase64;
}
}