Laravel项目中如何从控制器实现Firebase OTP短信发送功能
Laravel 服务端集成Firebase OTP短信验证码实现方案(无前端JS逻辑)
前置依赖安装与配置
- 首先通过Composer安装Firebase官方PHP Admin SDK:
composer require kreait/firebase-php - 从Firebase控制台下载服务账号JSON凭证文件,放置到项目
storage/app/firebase/目录下(目录不存在可自行创建) - 在
config/services.php中追加Firebase配置项:
'firebase' => [ 'credentials' => storage_path('app/firebase/service-account.json'), 'project_id' => env('FIREBASE_PROJECT_ID'), ],
- 在
.env文件中补充你的Firebase项目ID:FIREBASE_PROJECT_ID=你的Firebase项目ID
路由配置
在routes/web.php中添加两个POST路由,分别对应验证码发送和校验:
// 请求发送OTP验证码 Route::post('/otp/send', [OtpController::class, 'send'])->name('otp.send'); // 校验OTP验证码 Route::post('/otp/verify', [OtpController::class, 'verify'])->name('otp.verify');
生产环境建议给上述路由加throttle限流中间件,避免恶意刷取短信。
控制器逻辑实现
首先执行命令创建控制器:php artisan make:controller OtpController,然后编写对应方法:
发送OTP验证码方法
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Kreait\Firebase\Factory; use Kreait\Firebase\Auth; class OtpController extends Controller { protected $auth; public function __construct(Factory $firebase) { $this->auth = $firebase->createAuth(); } public function send(Request $request) { // 校验手机号格式,可根据你的业务区域调整规则 $request->validate([ 'phone' => 'required|string|regex:/^\+?[1-9]\d{1,14}$/' ]); try { // 服务端直接发起手机号验证,无需前端Recaptcha校验 $verification = $this->auth->startPhoneVerification($request->phone); // 将验证ID存入Session,*不要返回给前端*,避免泄露篡改 session(['firebase_verification_id' => $verification->verificationId()]); return back()->with('status', '验证码已发送至你的手机'); } catch (\Exception $e) { return back()->withErrors(['phone' => '验证码发送失败:'.$e->getMessage()]); } }
校验OTP验证码方法
继续在OtpController中追加verify方法:
public function verify(Request $request) { $request->validate([ 'otp_code' => 'required|digits:6' ]); try { // 从Session读取验证ID,和用户提交的验证码做校验 $verificationId = session('firebase_verification_id'); if (!$verificationId) { throw new \Exception('请先请求发送验证码'); } // 校验验证码有效性 $verified = $this->auth->verifyPhoneNumber($verificationId, $request->otp_code); // 校验通过后清除Session中的验证ID,避免重复使用 session()->forget('firebase_verification_id'); // 这里写你的后续业务逻辑,比如用户登录、注册等 // $verified->phoneNumber() 可以拿到已验证的手机号 return redirect()->route('dashboard')->with('status', '验证成功'); } catch (\Exception $e) { return back()->withErrors(['otp_code' => '验证码无效或已过期:'.$e->getMessage()]); } } }
前端Blade模板示例
完全不需要JavaScript代码,仅用普通表单提交即可:
{{-- 状态提示 --}} @if(session('status')) <div class="alert alert-success">{{ session('status') }}</div> @endif @if ($errors->any()) <div class="alert alert-danger"> @foreach ($errors->all() as $error) <p>{{ $error }}</p> @endforeach </div> @endif {{-- 发送验证码表单 --}} <form action="{{ route('otp.send') }}" method="POST"> @csrf <div> <label>手机号(带国际区号,比如+8613xxxxxxxxx)</label> <input type="tel" name="phone" required> </div> <button type="submit">发送验证码</button> </form> {{-- 校验验证码表单 --}} <form action="{{ route('otp.verify') }}" method="POST" style="margin-top: 20px"> @csrf <div> <label>6位验证码</label> <input type="text" name="otp_code" required maxlength="6"> </div> <button type="submit">提交验证</button> </form>
注意事项
- 手机号需要带国际区号,比如中国手机号格式为
+8613xxxxxxxxx,如果需要默认补区号可以在控制器send方法中自行处理 - Firebase OTP有官方发送频率限制,生产环境建议额外叠加业务层的短信发送频率校验
- 可以根据需求在发送验证码后加倒计时提示,纯服务端渲染即可,无需JS实现
内容的提问来源于stack exchange,提问作者Karat Khamin
相关产品推荐
相关产品推荐

