You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:28:43