php + redis 完成api接口的图形验证码

php + redis 完成api接口的图形验证码

1.生成产生图形验证码的url

$mobile = $_GET['mobile'];
$captcha = new SimpleCaptcha(array(),$mobile);
$captcha->maxWordLength=4;
$captcha->minWordLength=4;
$captcha->maxRotation=2;
$captcha->height=45;
$captcha->fonts=array(
'Duality'  => array('spacing' => 5, 'minSize' => 30, 'maxSize' => 38, 'font' => 'Duality.ttf'),
'Heineken' => array('spacing' => 5, 'minSize' => 24, 'maxSize' => 34, 'font' => 'Heineken.ttf'),
'Jura'     => array('spacing' => 5, 'minSize' => 28, 'maxSize' => 32, 'font' => 'Jura.ttf'),
);
$captcha->CreateImage();

class SimpleCaptcha {
    public $width  = 150;
    public $height = 60;
public $mobile = '';
public $wordsFile = 'words/en.php';
public $resourcesPath = '../../com/chungda/util/captcha/resources';
public $minWordLength = 6;
public $maxWordLength = 6;
public $redis_var = 'vcode';
public $backgroundColor = array(255, 255, 255);
public $colors = array(
    array(27,78,181), // blue
    array(22,163,35), // green
    array(214,36,7),  // red
);
public $shadowColor = array(0, 0, 0);
public $lineWidth = 2;
public $noisePoint=130;
public $fonts = array(
    'Antykwa'  => array('spacing' => -3, 'minSize' => 27, 'maxSize' => 30, 'font' => 'AntykwaBold.ttf'),
    'Candice'  => array('spacing' =>-1.5,'minSize' => 28, 'maxSize' => 31, 'font' => 'Candice.ttf'),
    'DingDong' => array('spacing' => -2, 'minSize' => 24, 'maxSize' => 30, 'font' => 'Ding-DongDaddyO.ttf'),
    'Duality'  => array('spacing' => 0, 'minSize' => 30, 'maxSize' => 38, 'font' => 'Duality.ttf'),
    'Heineken' => array('spacing' => 0, 'minSize' => 24, 'maxSize' => 34, 'font' => 'Heineken.ttf'),
    'Jura'     => array('spacing' => 0, 'minSize' => 28, 'maxSize' => 32, 'font' => 'Jura.ttf'),
    'StayPuft' => array('spacing' =>-1.5,'minSize' => 28, 'maxSize' => 32, 'font' => 'StayPuft.ttf'),
    'Times'    => array('spacing' => -2, 'minSize' => 28, 'maxSize' => 34, 'font' => 'TimesNewRomanBold.ttf'),
    'VeraSans' => array('spacing' => -1, 'minSize' => 20, 'maxSize' => 28, 'font' => 'VeraSansBold.ttf'),
);
public $Yperiod    = 12;
public $Yamplitude = 14;
public $Xperiod    = 11;
public $Xamplitude = 5;
public $maxRotation = 8;
public $scale = 2;
public $blur = true;
public $debug = false;
public $imageFormat = 'jpeg';
public $im;
public function __construct($config = array(),$mobile) {//传入mobile参数
    $this->mobile = $mobile;
}
public function CreateImage() {
    $ini = microtime(true);
    $this->ImageAllocate();
    $text = $this->GetCaptchaText();
    $fontcfg  = $this->fonts[array_rand($this->fonts)];
    $this->WriteText($text, $fontcfg);
    //存redis key:mobile => value:text
    require_once("../../include.php");
    $CRedis = new Redis();
    $CRedis->connect(REDIS_SERVER_SESSION,REDIS_PORT,3);
    $codeKey = "EX:".DOMAIN.":api:appPicAuth:cache:$this->mobile";
    $CRedis->setex($codeKey, 60, strtolower($text));
    $CRedis->close();
    if (!empty($this->lineWidth)) {
        $this->WriteLine();
    }
    if ($this->blur && function_exists('imagefilter')) {
        imagefilter($this->im, IMG_FILTER_GAUSSIAN_BLUR);
    }
    $this->ReduceImage();
    $this->createNoisePoint();

    if ($this->debug) {
        imagestring($this->im, 1, 1, $this->height-8,
            "$text {$fontcfg['font']} ".round((microtime(true)-$ini)*1000)."ms",
            $this->GdFgColor
        );
    }
    $this->WriteImage();
    $this->Cleanup();
}
protected function ImageAllocate() {
    if (!empty($this->im)) {
        imagedestroy($this->im);
    }
    $this->im = imagecreatetruecolor($this->width*$this->scale, $this->height*$this->scale);
    $this->GdBgColor = imagecolorallocate($this->im,
        $this->backgroundColor[0],
        $this->backgroundColor[1],
        $this->backgroundColor[2]
    );
    imagefilledrectangle($this->im, 0, 0, $this->width*$this->scale, $this->height*$this->scale, $this->GdBgColor);
    $color           = $this->colors[mt_rand(0, sizeof($this->colors)-1)];
    $this->GdFgColor = imagecolorallocate($this->im, $color[0], $color[1], $color[2]);
    if (!empty($this->shadowColor) && is_array($this->shadowColor) && sizeof($this->shadowColor) >= 3) {
        $this->GdShadowColor = imagecolorallocate($this->im,
            $this->shadowColor[0],
            $this->shadowColor[1],
            $this->shadowColor[2]
        );
    }
}
protected function GetCaptchaText() {
    $text = $this->GetDictionaryCaptchaText();
    if (!$text) {
        $text = $this->GetRandomCaptchaText();
    }
    return $text;
}
protected function GetRandomCaptchaText($length = null) {
    if (empty($length)) {
        $length = rand($this->minWordLength, $this->maxWordLength);
    }

    $words  = "abcdefghijlmnopqrstvwyz";
    $vocals = "aeiou";

    $text  = "";
    $vocal = rand(0, 1);
    for ($i=0; $i<$length; $i++) {
        if ($vocal) {
            $text .= substr($vocals, mt_rand(0, 4), 1);
        } else {
            $text .= substr($words, mt_rand(0, 22), 1);
        }
        $vocal = !$vocal;
    }
    return $text;
}
function GetDictionaryCaptchaText($extended = false) {
    if (empty($this->wordsFile)) {
        return false;
    }
    if (substr($this->wordsFile, 0, 1) == '/') {
        $wordsfile = $this->wordsFile;
    } else {
        $wordsfile = $this->resourcesPath.'/'.$this->wordsFile;
    }

    if (!file_exists($wordsfile)) {
        return false;
    }

    $fp     = fopen($wordsfile, "r");
    $length = strlen(fgets($fp));
    if (!$length) {
        return false;
    }
    $line   = rand(1, (filesize($wordsfile)/$length)-2);
    if (fseek($fp, $length*$line) == -1) {
        return false;
    }
    $text = trim(fgets($fp));
    fclose($fp);
    if ($extended) {
        $text   = preg_split('//', $text, -1, PREG_SPLIT_NO_EMPTY);
        $vocals = array('a', 'e', 'i', 'o', 'u');
        foreach ($text as $i => $char) {
            if (mt_rand(0, 1) && in_array($char, $vocals)) {
                $text[$i] = $vocals[mt_rand(0, 4)];
            }
        }
        $text = implode('', $text);
    }

    return $text;
}
protected function WriteLine() {

    $x1 = $this->width*$this->scale*.15;
    $x2 = $this->textFinalX;
    $y1 = rand($this->height*$this->scale*.40, $this->height*$this->scale*.65);
    $y2 = rand($this->height*$this->scale*.40, $this->height*$this->scale*.65);
    $width = $this->lineWidth/2*$this->scale;

    for ($i = $width*-1; $i <= $width; $i++) {
        imageline($this->im, $x1, $y1+$i, $x2, $y2+$i, $this->GdFgColor);
    }
}
protected function WriteText($text, $fontcfg = array()) {
    if (empty($fontcfg)) {
        $fontcfg  = $this->fonts[array_rand($this->fonts)];
    }
    $fontfile = $this->resourcesPath.'/fonts/'.$fontcfg['font'];
    $lettersMissing = $this->maxWordLength-strlen($text);
    $fontSizefactor = 1+($lettersMissing*0.09);
    $x      = 20*$this->scale;
    $y      = round(($this->height*27/40)*$this->scale);
    $length = strlen($text);
    for ($i=0; $i<$length; $i++) {
        $degree   = rand($this->maxRotation*-1, $this->maxRotation);
        $fontsize = rand($fontcfg['minSize'], $fontcfg['maxSize'])*$this->scale*$fontSizefactor;
        $letter   = substr($text, $i, 1);
        if ($this->shadowColor) {
            $coords = imagettftext($this->im, $fontsize, $degree,
                $x+$this->scale, $y+$this->scale,
                $this->GdShadowColor, $fontfile, $letter);
        }
        $coords = imagettftext($this->im, $fontsize, $degree,
            $x, $y,
            $this->GdFgColor, $fontfile, $letter);
        $x += ($coords[2]-$x) + ($fontcfg['spacing']*$this->scale);
    }

    $this->textFinalX = 0;//$x;
}
protected function WaveImage() {
    // X-axis wave generation
    $xp = $this->scale*$this->Xperiod*rand(1,3);
    $k = rand(0, 100);
    for ($i = 0; $i < ($this->width*$this->scale); $i++) {
        imagecopy($this->im, $this->im,
            $i-1, sin($k+$i/$xp) * ($this->scale*$this->Xamplitude),
            $i, 0, 1, $this->height*$this->scale);
    }
    $k = rand(0, 100);
    $yp = $this->scale*$this->Yperiod*rand(1,2);
    for ($i = 0; $i < ($this->height*$this->scale); $i++) {
        imagecopy($this->im, $this->im,
            sin($k+$i/$yp) * ($this->scale*$this->Yamplitude), $i-1,
            0, $i, $this->width*$this->scale, 1);
    }
}
protected function ReduceImage() {
    // Reduzco el tamaño de la imagen
    $imResampled = imagecreatetruecolor($this->width, $this->height);
    imagecopyresampled($imResampled, $this->im,
        0, 0, 0, 0,
        $this->width, $this->height,
        $this->width*$this->scale, $this->height*$this->scale
    );
    imagedestroy($this->im);
    $this->im = $imResampled;
}
public function createNoisePoint(){
    for($i=0;$i<$this->noisePoint;$i++){
        $pointColor=imagecolorallocate($this->im,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255));
        imagesetpixel($this->im,mt_rand(0,$this->width),mt_rand(0,$this->height),$pointColor);
    }

}
protected function WriteImage() {
    if ($this->imageFormat == 'png' && function_exists('imagepng')) {
        header("Content-type: image/png");
        imagepng($this->im);
    } else {
        header("Content-type: image/jpeg");
        imagejpeg($this->im, null, 80);
    }
}
protected function Cleanup() {
    imagedestroy($this->im);
}
}

效果:访问这个url就可以获取图形验证码并在redis中存储

2.返回生成产生图形验证码的url

url => http://www.”.DOMAIN.”/member/authCodeApp.php?mobile=”.mobile."&time=".time;
url最后的时间是为了防止重复访问,app端的图形验证码不变的情况发生

3.验证图形验证码,并发送短信

    //读取redis key:mobile => value:text
    $CRedis = new Redis();
    $CRedis->connect(REDIS_SERVER_SESSION,REDIS_PORT,3);
    $codeKey = "EX:".DOMAIN.":api:appPicAuth:cache:".$mobile;
    $mobilePicCode = $CRedis->get($codeKey);
    $CRedis->close();
    $code = self::random(6);
    if(strtolower($picCode) === $mobilePicCode)
    {
        return self::xsqJsonEncode($resultArr);
    }
    else
    {
        $resultArr = array("code" => "205", "msg" => "图形验证码错误");
        return self::xsqJsonEncode($resultArr);
    }

}

至此图形验证码的生成和验证已经完成
这里主要使用redis存储的目的是为了解决app端的session问题

你可能感兴趣的:(php)