手机注册api
2018年11月8日原理图
1.图片验证码获取接口
1.下载图片验证码包
1 |
composer require gregwar/captcha |
2 创建基类
1 |
php artisan make:controller Api/Controller |
编辑基类app/Http/Controllers/Api/Controller.php
(这里使用了Dingo)
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php namespace App\Http\Controllers\Api; use Illuminate\Http\Request; use Dingo\Api\Routing\Helpers; #Dingo的帮助函数 use App\Http\Controllers\Controller as BaseController; class Controller extends BaseController { use Helpers; } |
3.创建控制器和请求验证类
1 2 |
php artisan make:controller Api/CaptchasController php artisan make:request Api/CaptchaRequest |
编辑请求验证类app/Http/Requests/Api/CaptchaRequest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?php namespace App\Http\Requests\Api; use Dingo\Api\Http\FormRequest; #这里使用了Dingo的FormRequest class CaptchaRequest extends FormRequest { public function authorize() { return true; } public function rules() { return [ 'phone' => 'required|regex:/^1[34578]\d{9}$/|unique:users', ]; } } |
编辑控制器app/Http/Controllers/Api/CaptchasController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<?php namespace App\Http\Controllers\Api; use Illuminate\Http\Request; use Gregwar\Captcha\CaptchaBuilder; #这个是生成图片验证码的类 use App\Http\Requests\Api\CaptchaRequest; class CaptchasController extends Controller { /** * 生成验证码的方法 * @param CaptchaRequest $request * @param CaptchaBuilder $captchaBuilder * @return mixed */ public function store(CaptchaRequest $request, CaptchaBuilder $captchaBuilder) { $phone = $request->phone; #获取手机号 $key = 'captcha-' . str_random(15); #设置缓存键 $captcha = $captchaBuilder->build(); #获取图片验证码的,字符串 $expiredAt = now()->addMinutes(2); #设置过期时间 \Cache::put($key, ['phone' => $phone, 'code' => $captcha->getPhrase()], $expiredAt); #缓存 $result = ['captcha_key' => $key, 'expired_at' => $expiredAt->toDateTimeString(), 'captcha_image_content' => $captcha->inline()]; #这里存放着缓存键,过期时间,图片二进制 return $this->response->array($result)->setStatusCode(201); #返回数据 } } |
4,编辑路由
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?php use Illuminate\Http\Request; $api = app('Dingo\Api\Routing\Router'); $api->version('v1', ['namespace' => 'App\Http\Controllers\Api'], function ($api) { #定义了一个命名空间 $api->group(['middleware' => 'api.throttle', 'limit' => 10, 'expires' => 1], function ($api) { #定义了请求次数 $api->post('captchas', 'CaptchasController@store')->name('api.captchas.store'); #获取图片验证码的接口 }); }); |
2编辑短信验证码的方法
前提需要接入短信发送服务
1创建控制器和表单请求验证类
1 2 |
php artisan make:controller Api/VerificationCodesController php artisan make:request Api/VerificationCodeRequest |
编辑表单验证类app/Http/Requests/Api/VerificationCodeRequest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<?php namespace App\Http\Requests\Api; use Dingo\Api\Http\FormRequest; class VerificationCodeRequest extends FormRequest { public function authorize() { return true; } public function rules() { return [ 'captcha_key' => 'required|string', 'captcha_code' => 'required|string', ]; } public function attributes() { return [ 'captcha_key' => '图片验证码 key', 'captcha_code' => '图片验证码', ]; } } |
编辑app/Http/Controllers/Api/VerificationCodesController
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
<?php namespace App\Http\Controllers\Api; use Illuminate\Http\Request; use Overtrue\EasySms\EasySms; use App\Http\Requests\Api\VerificationCodeRequest; class VerificationCodesController extends Controller { /** * 发送短信的方法 * @param VerificationCodeRequest $request * @param EasySms $easySms * @return mixed * @throws \Exception */ public function store(VerificationCodeRequest $request, EasySms $easySms) { $captchaData = \Cache::get($request->captcha_key); #从缓存中获取数据 if (!$captchaData) { #如果数据不存在缓存失效 return $this->response->error('图片验证码已失效', 422); #返回验证失效信息 } if (!hash_equals($captchaData['code'], $request->captcha_code)) { #判断验证码是否一致,hash_equals 是可防止时序攻击的字符串比较。 \Cache::forget($request->captcha_key); #验证错误就清除缓存 return $this->response->errorUnauthorized('验证码错误'); #返回错误信息 } $phone = $captchaData['phone']; #获取手机号 if (!app()->environment('production')) { #判断是否是生产环境 $code = '1234'; } else { $code = str_pad(random_int(1, 9999), 4, 0, STR_PAD_LEFT); #生成4位随机数,左侧补0 try { $result = $easySms->send($phone, ['content' => "【Lbbs社区】您的验证码是{$code}。如非本人操作,请忽略本短信"]); } catch (\Overtrue\EasySms\Exceptions\NoGatewayAvailableException $exception) { $message = $exception->getException('yunpian')->getMessage(); return $this->response->errorInternal($message ?? '短信发送异常'); #??语法糖,如果变量存在且值不为NULL, 它就会返回自身的值,否则返回它的第二个操作数 } } $key = 'verificationCode_'.str_random(15); #设置缓存键 $expiredAt = now()->addMinutes(10); #设置过期时间10分钟之后 \Cache::put($key, ['phone' => $phone, 'code' => $code], $expiredAt); #缓存验证码 10分钟过期。 \Cache::forget($request->captcha_key); #清除图片验证码缓存 return $this->response->array(['key' => $key, 'expired_at' => $expiredAt->toDateTimeString(),])->setStatusCode(201); #返回缓存键,和过期时间 } } |
3编辑路由
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?php use Illuminate\Http\Request; $api = app('Dingo\Api\Routing\Router'); $api->version('v1', ['namespace' => 'App\Http\Controllers\Api'], function ($api) { #定义了一个命名空间 $api->group(['middleware' => 'api.throttle', 'limit' => 10, 'expires' => 1,], function ($api) { #一分钟可以请求10次 $api->post('captchas', 'CaptchasController@store')->name('api.captchas.store'); #获取图片验证码的接口 $api->post('verificationCodes', 'VerificationCodesController@store')->name('api.verificationCodes.store'); #短信验证码 }); }); |
3.编辑注册接口
1修改数据结构
1 |
php artisan make:migration add_phone_to_users_table --table=users |
编辑database/migrations/{your_date}_add_phone_to_users_table.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class AddPhoneToUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('users', function (Blueprint $table) { $table->string('phone')->nullable()->unique()->after('name'); $table->string('email')->nullable()->change(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('users', function (Blueprint $table) { $table->dropColumn('phone'); $table->string('email')->nullable(false)->change(); }); } } |
执行迁移命令
1 |
php artisan migrate |
2,创建控制器和请求验证类
1 2 |
php artisan make:controller Api/UsersController php artisan make:request Api/UserRequest |
编辑请求验证类
打开文件app/Http/Requests/Api/UserRequest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<?php namespace App\Http\Requests\Api; use Dingo\Api\Http\FormRequest; class UserRequest extends FormRequest { public function authorize() { return true; } /** * 验证规则 * @return array */ public function rules() { return [ 'name' => 'required|between:3,25|regex:/^[A-Za-z0-9\-\_]+$/|unique:users,name', 'password' => 'required|string|min:6', 'verification_key' => 'required|string', 'verification_code' => 'required|string', ]; } /** * 返回的提示信息 * @return array */ public function attributes() { return [ 'verification_key' => '短信验证码 key', 'verification_code' => '短信验证码', ]; } } |
编辑控制器
打开文件app/Http/Controllers/Api/UsersController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<?php namespace App\Http\Controllers\Api; use App\Models\User; use Illuminate\Http\Request; use App\Http\Requests\Api\UserRequest; class UsersController extends Controller { /** * 创建用户的api接口 * @param UserRequest $request * @return mixed */ public function store(UserRequest $request) { $verifyData = \Cache::get($request->verification_key); #从缓存中获取验证码 if (!$verifyData) { #如果没有获取到验证码验证码就是过期的 return $this->response->error('验证码已失效', 422); } if (!hash_equals($verifyData['code'], $request->verification_code)) { #判断验证码是否一致,hash_equals 是可防止时序攻击的字符串比较。 return $this->response->errorUnauthorized('验证码错误'); #返回401 用户请求错误 } $user = User::create([ #开始创建数据 'name' => $request->name, 'phone' => $verifyData['phone'], #缓存中的手机号 'password' => bcrypt($request->password), ]); \Cache::forget($request->verification_key); #清除验证码缓存 return $this->response->created(); #返回创建成功的提示信息 } } |
3,修改模型
打开文件app/Models/User.php
1 2 3 |
protected $fillable = [ 'name', 'email', 'password', 'introduction', 'avatar','phone' ]; |
4,编辑路由
打开文件routes/api.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
. . . $api->version('v1', ['namespace' => 'App\Http\Controllers\Api'], function ($api) { #定义了一个命名空间 $api->group(['middleware' => 'api.throttle', 'limit' => 10, 'expires' => 1,], function ($api) { #一分钟可以请求10次 $api->post('captchas', 'CaptchasController@store')->name('api.captchas.store'); #获取图片验证码的接口 $api->post('verificationCodes', 'VerificationCodesController@store')->name('api.verificationCodes.store'); #短信验证码 $api->post('users', 'UsersController@store')->name('api.users.store'); #用户注册接口 }); }); . . . |