Laravel 5.5 注册登录验证码

发布时间:2018-04-01 编辑:小张个人博客 查看次数:4013

我们的注册功能存在一个问题,因我们表单未添加任何防护,恶意用户可以轻易使用机器人自动化注册新用户。机器人自由注册,对我们站点稳定性来讲是巨大的威胁,恶意用户可以很轻易的通过机器人程序在短时间内,注册大量用户,甚至于填满我们的数据库。

php 验证码

验证码是防止恶意破解密码、刷票、论坛灌水、刷页的手段。验证码有 多种类型。 本项目中我们将使用图片验证码,其原理是让用户输入一个扭曲变形的图片上所显示的文字或数字,扭曲变形是为了避免被光学字符识别软件(OCR)自动辨识。由于计算机无法识别验证码的图片,所以回答出问题的用户就可以被认为是人类。

接下来我们将使用验证码来防卫的用户注册功能。

我们将以 ValidateCode.php 作为基础来实现 Laravel 中的验证码功能。

<?php

namespace App\Tool\Validate;

//验证码类
class ValidateCode
{
    private $charset = 'abcdefghkmnprstuvwxyzABCDEFGHKMNPRSTUVWXYZ23456789';//随机因子
    private $code;//验证码
    private $codelen = 4;//验证码长度
    private $width = 130;//宽度
    private $height = 50;//高度
    private $img;//图形资源句柄
    private $font;//指定的字体
    private $fontsize = 20;//指定字体大小
    private $fontcolor;//指定字体颜色

    //构造方法初始化
    public function __construct()
    {
        $this->font = public_path() . '/fonts/Elephant.ttf';//注意字体路径要写对,否则显示不了图片
        $this->createCode();
    }
    //生成随机码
    private function createCode()
    {
        $_len = strlen($this->charset) - 1;
        for ($i = 0;$i < $this->codelen;++$i) {
            $this->code .= $this->charset[mt_rand(0, $_len)];
        }
    }
    //生成背景
    private function createBg()
    {
        $this->img = imagecreatetruecolor($this->width, $this->height);
        $color = imagecolorallocate($this->img, mt_rand(157, 255), mt_rand(157, 255), mt_rand(157, 255));
        imagefilledrectangle($this->img, 0, $this->height, $this->width, 0, $color);
    }
    //生成文字
    private function createFont()
    {
        $_x = $this->width / $this->codelen;
        for ($i = 0;$i < $this->codelen;++$i) {
            $this->fontcolor = imagecolorallocate($this->img, mt_rand(0, 156), mt_rand(0, 156), mt_rand(0, 156));
            imagettftext($this->img, $this->fontsize, mt_rand(-30, 30), $_x * $i + mt_rand(1, 5), $this->height / 1.4, $this->fontcolor, $this->font, $this->code[$i]);
        }
    }
    //生成线条、雪花
    private function createLine()
    {
      //线条
      for ($i = 0;$i < 6;++$i) {
          $color = imagecolorallocate($this->img, mt_rand(0, 156), mt_rand(0, 156), mt_rand(0, 156));
          imageline($this->img, mt_rand(0, $this->width), mt_rand(0, $this->height), mt_rand(0, $this->width), mt_rand(0, $this->height), $color);
      }
      //雪花
      for ($i = 0;$i < 100;++$i) {
          $color = imagecolorallocate($this->img, mt_rand(200, 255), mt_rand(200, 255), mt_rand(200, 255));
          imagestring($this->img, mt_rand(1, 5), mt_rand(0, $this->width), mt_rand(0, $this->height), '*', $color);
      }
    }
    //输出
    private function outPut()
    {
        header('Content-type:image/png');
        imagepng($this->img);
        imagedestroy($this->img);
    }
    //对外生成
    public function doimg()
    {
        $this->createBg();
        $this->createLine();
        $this->createFont();
        $this->outPut();
    }
    //获取验证码
    public function getCode()
    {
        return strtolower($this->code);
    }
}

可以看到这些配置选项都非常通俗易懂,$codelen, $width, $height , $fontsize$fontcolor 分别是定义验证码类型,你可以在此修改对应选项自定义验证码的长度、宽度、高度、字体大小、文字颜色等属性。

新建 ValidateController.php

    // 生成验证码
    public function create(Request $request) {
        $validateCode = new ValidateCode;
        // 验证码保存到SESSION中
        $request->session()->put('validate_code', $validateCode->getCode());
        return $validateCode->doimg();
    }

设置路由
Route::get('captcha', 'Auth\[email protected]')->name('create');

前端展示,分为两步:

1、前端展示 —— 生成验证码给用户展示,并收集用户输入的答案;

2、后端验证 —— 接收答案,检测用户输入的验证码是否正确。

接下来我们请将 register.blade.php 文件中找个合适位置添加为以下内容:

<div class="form-group {{ $errors->has('captcha') ? ' has-error' : '' }}">
    <label for="captcha" class="col-md-4 control-label">Captcha</label>

    <div class="col-md-6">
	<input id="captcha" class="form-control" name="captcha" >

	<img class="thumbnail captcha" src="{{ url('captcha') }}" onclick="this.src='{{ url('captcha') }}'+'?'+Math.random()" title="点击图片重新获取验证码">

	@if ($errors->has('captcha'))
	    <span class="help-block">
		<strong>{{$errors->first('captcha') }}</strong>
	    </span>
	@endif
    </div>
</div>

Laravel 验证码

后端验证( RedirectsUsers.php )

前端展示部分我们已经开发完毕,接下来处理后端验证逻辑。ValidateCode.php 能很好的兼容 Laravel 5.5 

public function register(Request $request){
        $data = Input::all();
        $rules = [
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|min:6|confirmed',
            'captcha' => 'required',
        ];
        $message = [
            'captcha.required' => '验证码不能为空',
        ];
        // 验证数据
        $validator = Validator::make($data,$rules,$message);
        if($validator -> passes()){
            if($data['captcha'] != session('validate_code')){
               $validator->errors()->add('captcha', '请输入正确的验证码!'); // 添加错误提示信息
                return back() -> withErrors($validator);
            }
            event(new Registered($user = $this->create($request->all())));
            $this->guard()->login($user);
            return $this->registered($request, $user)
                ?: redirect($this->redirectPath());
        }else{
            return back() -> withErrors($validator);
        }

    }

以下内容对上述代码的一个说明:

验证规则

如果传入的请求参数未通过给定的验证规则呢?正如前面所提到的,Laravel 会自动把用户重定向到先前的位置。

另外,所有的验证错误信息会被自动 闪存至 session

我们不必在 GET 路由中将错误消息显式绑定到视图。因为 Lavarel 会检查在 Session 数据中的错误信息,并自动将其绑定到视图(如果存在)。

而其中的变量 $errorsIlluminate\Support\MessageBag 的一个实例。要获取关于这个对象的更多信息

  $rules = [
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|min:6|confirmed',
            'captcha' => 'required',
        ];

自定义错误消息

如果有需要的话,你也可以自定义错误消息取代默认值进行验证。有几种方法可以指定自定义消息。

首先,你可以将自定义消息作为第三个参数传递给 Validator::make 方法:

 $message = [
            'captcha.required' => '验证码不能为空',
        ];

处理错误消息

Validator 实例上调用 errors 方法后,会得到一个 Illuminate\Support\MessageBag 实例,

该实例具有各种方便的处理错误消息的方法。$errors 变量是自动提供给所有视图的 MessageBag 类的一个实例。

// 验证数据
$validator = Validator::make($data,$rules,$message);
if($validator -> passes()){
    if($data['captcha'] != session('validate_code')){
       $validator->errors()->add('captcha', '请输入正确的验证码!'); // 添加错误提示信息
	return back() -> withErrors($validator);
    }
    event(new Registered($user = $this->create($request->all())));

    $this->guard()->login($user);

    return $this->registered($request, $user)
	?: redirect($this->redirectPath());

}else{
    return back() -> withErrors($validator);
}

接下来继续测试:

自定义错误消息

查看所有字段的错误消息

如果你想要得到所有字段的错误消息,可以使用 all 方法:

foreach ($errors->all() as $message) {
 //

}

查看特定字段的第一个错误消息

如果要查看特定字段的第一个错误消息,可以使用 first 方法:

$errors = $validator->errors();
echo $errors->first('email');




出处:小张个人博客

网址:http://blog.023xs.cn/

您的支持是对博主最大的鼓励,感谢您的认真阅读。欢迎转载,但请保留该声明。

顶部

Copyright © 小张个人博客 All Rights Reserved 渝ICP备15006773号-1

联系方式:[email protected] | 本站文章仅供学习和参考

渝公网安备 50024102500267号