基于NuxtJS PWA,如何在自定义OTP登录API下使用Laravel Sanctum?
用Laravel Sanctum搭配自定义OTP登录API实现NuxtJS PWA认证
首先得明确:Sanctum的核心是帮你处理基于会话的认证和CSRF防护,它完全不强制你使用默认的/login路由——你可以用自定义的OTP接口完成用户认证,只要在验证通过后正确创建用户会话就行。下面是具体的实现步骤:
1. 完成Laravel Sanctum的基础配置
先确保你已经完成Sanctum的基础安装(比如composer require laravel/sanctum、迁移、中间件配置),然后重点调整以下配置:
在
config/sanctum.php里,把你的NuxtJS PWA域名加入stateful数组,确保Sanctum能识别并维护会话:'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( '%s%s', 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : '' ))),记得把你的PWA实际域名(比如
yourapp.com)补充进去。在
config/cors.php里开启凭证支持,并设置允许的源:'supports_credentials' => true, 'allowed_origins' => ['http://localhost:3000', 'https://your-pwa-domain.com'], // 替换成你的PWA地址
2. 编写自定义OTP登录API
核心逻辑是:验证OTP通过后,调用Auth::login()创建用户会话——这是让Sanctum识别用户已认证的关键。
在routes/api.php里定义路由:
use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; Route::post('/login/otp', function (Request $request) { // 1. 验证请求参数 $request->validate([ 'phone' => 'required|string', 'otp' => 'required|string|size:6', ]); // 2. 验证OTP有效性(替换成你实际的OTP校验逻辑) $user = \App\Models\User::where('phone', $request->phone)->first(); if (!$user || !hash_equals($user->otp, $request->otp)) { return response()->json(['message' => 'Invalid OTP'], 401); } // 3. 关键:登录用户,创建会话 Auth::login($user); // 4. 可选:清除已使用的OTP,避免重复验证 $user->otp = null; $user->save(); return response()->json([ 'message' => 'Authenticated successfully', 'user' => $user ]); });
3. NuxtJS端的认证流程实现
因为是PWA,要确保请求携带会话cookie,所以先配置HTTP客户端支持凭证:
3.1 配置Axios(如果使用@nuxtjs/axios)
在nuxt.config.js里设置:
export default { modules: ['@nuxtjs/axios'], axios: { baseURL: 'https://your-laravel-api-domain.com/api', // 替换成你的API地址 credentials: true, // 允许携带cookie,关键配置 } }
3.2 实现OTP登录逻辑
发起登录请求前,需要先获取Sanctum的CSRF令牌(POST请求必须验证CSRF):
// 示例:登录页面的methods方法 async loginWithOTP() { try { // 第一步:获取CSRF令牌,Sanctum会自动设置会话cookie await this.$axios.get('/sanctum/csrf-cookie'); // 第二步:发送OTP登录请求 const response = await this.$axios.post('/login/otp', { phone: this.phone, otp: this.otp }); // 登录成功后,将用户信息存入Vuex或localStorage this.$store.commit('auth/setUser', response.data.user); // 跳转到认证后页面 this.$router.push('/dashboard'); } catch (error) { console.error('Login failed:', error.response.data); // 这里可以添加错误提示逻辑 } }
4. 后续API请求的认证处理
只要用户登录成功(会话cookie已设置),后续的API请求会自动带上认证信息。比如在Vuex中获取用户数据:
async fetchUserData({ commit }) { try { // 这个路由需要添加`auth:sanctum`中间件 const response = await this.$axios.get('/user'); commit('setUser', response.data); } catch (error) { // 处理未认证情况,比如跳回登录页 this.$router.push('/login'); } }
5. 登出功能实现
Laravel端添加登出路由
Route::post('/logout', function (Request $request) { Auth::logout(); return response()->json(['message' => 'Logged out successfully']); })->middleware('auth:sanctum');
Nuxt端实现登出方法
async logout() { try { await this.$axios.post('/logout'); this.$store.commit('auth/clearUser'); this.$router.push('/login'); } catch (error) { console.error('Logout failed:', error); } }
额外注意事项
- 确保PWA和Laravel API处于同一顶级域名下(或正确配置跨域),否则浏览器可能会阻止cookie传递;
- OTP的生成和存储要保证安全,比如用哈希存储、设置过期时间。
内容的提问来源于stack exchange,提问作者Milad Mohammadi
相关产品推荐
相关产品推荐

